C++职工信息管理系统实战:数据模型、持久化与查询统计避坑指南
简介这是一份面向C初学者与课程设计学习者的职工信息管理系统完整项目源码基于C面向对象思想开发可在VC6.0环境下编译运行适合用来理解类设计、文件持久化与模块化编程。压缩包内共31个文件约270KB以cpp实现文件与h头文件为核心另有obj、pdb、ilk等编译中间产物以及dsw、dsp工程文件和doc说明文档并附带少量jpg图片资源完整保留了从源码到可执行文件的开发痕迹。项目围绕Employee、Department等类展开通过继承与多态组织职工信息借助fstream完成数据的读写与持久化主程序、数据库操作、薪资计算等功能被拆分到不同源文件中结构清晰。目前已有217人学习下载对于想动手实践C语法、STL与文件操作或需要课程设计参考的读者可从中获得完整的工程组织思路与可运行的实现范例。1. 从一份“能跑但不敢改”的职工管理系统说起很多做 C 课程设计或内部小工具的人都会碰到同一个尴尬代码能编译、能录入、能查询但一旦要加个“按部门统计薪资”或者“把数据换成二进制存储”整个工程就像一团被猫抓过的毛线。职工信息管理系统这个题目几乎成了 C 面向对象、文件持久化、容器选型、内存管理的综合练兵场。它不复杂但能把一个开发者对封装、生命周期、异常边界的理解暴露得干干净净。这篇文章面向两类人一是正在做 C 职工信息管理系统、想把它写到能拿得出手的在校生或转行者二是需要快速交付一个内部人员台账工具、又不想引入数据库和框架的一线开发者。我会按“先定数据模型再落持久化再补查询与统计最后处理边界”的顺序把可复现的代码、参数和踩坑点摊开讲。2. 职工信息管理系统怎么定数据模型从字段到内存布局2.1 先想清楚“职工”到底有哪些字段别急着写类很多人一上来就class Employee { ... }结果写到一半发现要加“离职日期”“部门编号”“薪资等级”于是回头改构造函数、改文件读写、改打印函数改到怀疑人生。我的习惯是先用一张表把字段定死再决定哪些字段参与查询、哪些参与排序、哪些需要持久化。字段名类型是否必填用途备注idint是唯一标识建议从 1000 起避免和默认 0 混淆namestring是姓名允许中文注意文件编码genderchar是性别用 M/F 或 0/1别用中文单字ageint是年龄范围 16–70录入时校验departmentstring是部门建议固定枚举避免“技术部/技术中心”混用positionstring否岗位可为空salarydouble是月薪用 double 够用别用 floathireDatestring是入职日期统一 YYYY-MM-DD方便字符串排序这张表定完类的成员基本就确定了。注意salary用double而不是float因为 float 在累加统计时误差会肉眼可见hireDate用字符串而不是time_t是为了文件可读性和跨平台省事。部门字段我强烈建议用枚举或固定字符串数组否则后面按部门统计时会出现“研发部”和“研发中心”被当成两个部门。2.2 用 struct 还是 class构造函数怎么写才不翻车职工信息管理系统里Employee 更适合用struct还是class我的判断是如果字段全部公开、没有行为用struct一旦要加校验、格式化输出、序列化就用class并把字段设为 private。下面是一个我常用的最小可用版本#include string #include iostream #include stdexcept class Employee { private: int id_; std::string name_; char gender_; int age_; std::string department_; std::string position_; double salary_; std::string hireDate_; public: Employee() : id_(0), gender_(M), age_(0), salary_(0.0) {} Employee(int id, const std::string name, char gender, int age, const std::string dept, const std::string pos, double salary, const std::string hireDate) : id_(id), name_(name), gender_(gender), age_(age), department_(dept), position_(pos), salary_(salary), hireDate_(hireDate) { if (age 16 || age 70) { throw std::invalid_argument(age out of range); } if (salary 0) { throw std::invalid_argument(salary cannot be negative); } } int getId() const { return id_; } const std::string getName() const { return name_; } const std::string getDepartment() const { return department_; } double getSalary() const { return salary_; } const std::string getHireDate() const { return hireDate_; } void setSalary(double s) { if (s 0) throw std::invalid_argument(salary cannot be negative); salary_ s; } void setDepartment(const std::string d) { department_ d; } void print() const { std::cout id_ | name_ | gender_ | age_ | department_ | position_ | salary_ | hireDate_ \n; } };这段代码的关键点不在语法而在两个校验年龄范围和薪资非负。很多人的系统在录入时不做校验结果文件里出现age -1或者salary -5000统计平均薪资时直接算出负数排查半天才发现是录入环节漏了。构造函数抛异常调用方用 try-catch 包住这是最省心的做法。2.3 容器选型vector、list、map 到底用哪个职工信息管理系统最常见的操作是按 id 查找、遍历打印、按部门筛选、按薪资排序。这四种操作的权重决定了容器选型。std::vectorEmployee遍历和排序最快内存连续缓存友好。适合“数据量几千到几万、以遍历和排序为主”的场景。std::listEmployee插入删除快但遍历慢、缓存不友好。除非你频繁在中间插入删除否则不推荐。std::mapint, Employee按 id 查找 O(log n)但遍历时内存不连续排序也不如 vector 方便。std::unordered_mapint, Employee按 id 查找 O(1)但同样不擅长排序和范围查询。我的建议是主存储用std::vectorEmployee同时维护一个std::unordered_mapint, size_t做 id 到下标的索引。这样遍历、排序、按 id 查找都快。下面是一个简化的管理类骨架#include vector #include unordered_map #include algorithm class EmployeeManager { private: std::vectorEmployee employees_; std::unordered_mapint, size_t idIndex_; public: bool add(const Employee e) { if (idIndex_.count(e.getId())) return false; idIndex_[e.getId()] employees_.size(); employees_.push_back(e); return true; } Employee* findById(int id) { auto it idIndex_.find(id); if (it idIndex_.end()) return nullptr; return employees_[it-second]; } void sortBySalary() { std::sort(employees_.begin(), employees_.end(), [](const Employee a, const Employee b) { return a.getSalary() b.getSalary(); }); rebuildIndex(); } void rebuildIndex() { idIndex_.clear(); for (size_t i 0; i employees_.size(); i) { idIndex_[employees_[i].getId()] i; } } };注意sortBySalary之后必须调用rebuildIndex()否则 id 索引里的下标就全乱了。这是很多人踩过的坑排序后按 id 查找返回的是错误的职工。索引和主存储的一致性必须靠“任何改变顺序的操作后重建索引”来保证。3. 文件持久化怎么做才不丢数据文本、二进制与 CSV 的取舍3.1 文本格式可读性最好但解析要小心文本格式适合调试和人工检查常见做法是每行一条记录字段用|或,分隔。下面是一个写入函数#include fstream #include sstream void saveToText(const std::vectorEmployee list, const std::string path) { std::ofstream ofs(path, std::ios::out | std::ios::trunc); if (!ofs) throw std::runtime_error(cannot open file for write); for (const auto e : list) { ofs e.getId() | e.getName() | e.getGender() | e.getAge() | e.getDepartment() | e.getPosition() | e.getSalary() | e.getHireDate() \n; } }读取时按|分割注意姓名和部门里不能包含|否则解析会错位。如果确实可能包含就要用转义或者换成 CSV 加引号的方案。读取函数里最容易翻车的是std::stoi和std::stod抛异常所以每个字段转换都要包 try-catch遇到坏行就跳过并记录行号。3.2 二进制格式快、紧凑但跨平台和版本兼容是坑二进制格式适合数据量大、不需要人工查看的场景。写法如下void saveToBinary(const std::vectorEmployee list, const std::string path) { std::ofstream ofs(path, std::ios::binary | std::ios::trunc); if (!ofs) throw std::runtime_error(cannot open binary file); size_t n list.size(); ofs.write(reinterpret_castconst char*(n), sizeof(n)); for (const auto e : list) { int id e.getId(); int age e.getAge(); double salary e.getSalary(); ofs.write(reinterpret_castconst char*(id), sizeof(id)); ofs.write(reinterpret_castconst char*(age), sizeof(age)); ofs.write(reinterpret_castconst char*(salary), sizeof(salary)); // string 不能直接 write需要先写长度再写内容 const std::string name e.getName(); size_t len name.size(); ofs.write(reinterpret_castconst char*(len), sizeof(len)); ofs.write(name.data(), len); } }二进制格式的三个坑第一std::string不能直接write必须先写长度再写内容第二不同平台int和double的字节序可能不同跨平台交换数据要统一字节序第三结构体如果有虚函数或者对齐填充直接写整个对象会写入垃圾数据。所以我的习惯是逐字段写不写整个对象。3.3 CSV 格式和表格软件互通但引号和换行要处理CSV 的好处是能直接用表格软件打开适合给非技术人员看。但 CSV 的规则比想象中复杂字段里如果有逗号、引号、换行必须用双引号包起来内部的双引号要写成两个。下面是一个简化的 CSV 写入std::string escapeCsv(const std::string s) { bool needQuote s.find_first_of(,\\n) ! std::string::npos; if (!needQuote) return s; std::string out \; for (char c : s) { if (c ) out \\; else out c; } out \; return out; } void saveToCsv(const std::vectorEmployee list, const std::string path) { std::ofstream ofs(path); ofs id,name,gender,age,department,position,salary,hireDate\n; for (const auto e : list) { ofs e.getId() , escapeCsv(e.getName()) , e.getGender() , e.getAge() , escapeCsv(e.getDepartment()) , escapeCsv(e.getPosition()) , e.getSalary() , e.getHireDate() \n; } }如果只做内部工具字段里几乎不会出现逗号和引号可以省掉转义但只要有一次用户输入了带逗号的部门名整个 CSV 就会错列。所以转义函数建议保留。4. 查询、统计与排序把常用操作写成可复用的函数4.1 按部门筛选和按薪资区间查询查询功能的核心是“条件组合”。我一般写一个通用的过滤函数接受一个谓词#include functional std::vectorEmployee filter(const std::vectorEmployee list, std::functionbool(const Employee) pred) { std::vectorEmployee result; for (const auto e : list) { if (pred(e)) result.push_back(e); } return result; } // 用法按部门筛选 auto tech filter(employees, [](const Employee e) { return e.getDepartment() 技术部; }); // 用法薪资区间 auto mid filter(employees, [](const Employee e) { return e.getSalary() 8000 e.getSalary() 15000; });这种写法的好处是查询逻辑和数据结构解耦新增查询条件不用改管理类。缺点是每次查询都复制一份结果数据量大时内存翻倍。如果数据量超过十万建议返回下标或者迭代器而不是复制对象。4.2 部门薪资统计平均、最高、最低一次算完统计功能最怕的是多次遍历。下面这个函数一次遍历算出部门人数、总薪资、最高和最低#include map #include limits struct DeptStat { int count 0; double total 0.0; double maxSalary std::numeric_limitsdouble::lowest(); double minSalary std::numeric_limitsdouble::max(); }; std::mapstd::string, DeptStat statByDepartment( const std::vectorEmployee list) { std::mapstd::string, DeptStat stats; for (const auto e : list) { auto s stats[e.getDepartment()]; s.count; s.total e.getSalary(); if (e.getSalary() s.maxSalary) s.maxSalary e.getSalary(); if (e.getSalary() s.minSalary) s.minSalary e.getSalary(); } return stats; }注意maxSalary初始化为lowest()而不是 0否则如果所有薪资都是负数虽然业务上不该出现最高薪资会算错。minSalary初始化为max()同理。统计结果打印时平均薪资要判断count 0避免除零。4.3 排序按薪资、按入职日期、按部门薪资二级排序排序用std::sort加 lambda 最灵活。按入职日期排序时因为日期是YYYY-MM-DD格式字符串比较等价于日期比较// 按入职日期升序 std::sort(employees.begin(), employees.end(), [](const Employee a, const Employee b) { return a.getHireDate() b.getHireDate(); }); // 按部门升序同部门按薪资降序 std::sort(employees.begin(), employees.end(), [](const Employee a, const Employee b) { if (a.getDepartment() ! b.getDepartment()) return a.getDepartment() b.getDepartment(); return a.getSalary() b.getSalary(); });二级排序的写法是先比较第一关键字不相等就直接返回相等再比较第二关键字。很多人写成return a.dept b.dept a.salary b.salary这是错的因为当部门相等时a.dept b.dept为 false整个表达式为 false排序结果不稳定。正确写法必须用 if 分开。5. 避坑与排查职工信息管理系统最常见的 5 个翻车现场5.1 现象程序运行到一半崩溃提示 vector 下标越界原因用employees_[idIndex_[id]]访问时id 不存在于idIndex_operator[]会插入一个默认值 0然后拿 0 去访问 vector如果 vector 为空就崩溃。解决访问前先find判断迭代器是否等于end()不要用operator[]做查找。5.2 现象保存后再读取中文姓名变成乱码原因文件写入时用了默认编码读取时用了另一种编码或者std::string按字节截断。解决统一用 UTF-8读取时按字节读不要按字符数截断如果要在 Windows 控制台显示需要设置控制台代码页或者干脆用文件查看。5.3 现象排序后按 id 查找返回的职工对不上原因排序改变了 vector 中元素的位置但 id 索引里存的下标没有更新。解决任何改变元素顺序的操作后调用rebuildIndex()重建索引。这是最容易被忽略的一致性维护点。5.4 现象删除一个职工后后面所有职工的 id 索引全部错位原因用vector::erase删除元素后被删除位置之后的所有元素下标都减一但索引没更新。解决删除后立即重建索引或者用“标记删除 定期压缩”的策略避免频繁重建。5.5 现象薪资统计结果出现极小的小数误差比如 12345.678999999原因double累加时的浮点误差。解决统计时用double没问题但显示时用std::fixed和std::setprecision(2)控制小数位如果对金额精度要求高改用整数分存储显示时除以 100。6. 把系统写到能交付从单文件到多文件再到可测试6.1 拆分头文件和源文件别把所有代码塞进 main.cpp单文件写到最后通常超过一千行改一个函数要滚半天。我的拆分方式是Employee.h放类定义Employee.cpp放实现EmployeeManager.h放管理类EmployeeManager.cpp放实现FileIO.h和FileIO.cpp放持久化main.cpp只做菜单和调用。这样编译单元清晰改一个文件不用全量重编。6.2 用断言和单元测试保护核心逻辑职工信息管理系统的核心逻辑是增删改查和统计这些函数应该可以在没有菜单的情况下单独测试。下面是一个极简的测试写法不引入任何框架#include cassert void testAddAndFind() { EmployeeManager mgr; Employee e(1001, 张三, M, 28, 技术部, 工程师, 12000.0, 2020-07-01); assert(mgr.add(e) true); assert(mgr.add(e) false); // 重复 id 应该失败 Employee* p mgr.findById(1001); assert(p ! nullptr); assert(p-getName() 张三); } void testStat() { std::vectorEmployee list; list.emplace_back(1, A, M, 25, 技术部, , 10000.0, 2021-01-01); list.emplace_back(2, B, F, 30, 技术部, , 20000.0, 2019-01-01); auto stats statByDepartment(list); assert(stats[技术部].count 2); assert(stats[技术部].total 30000.0); assert(stats[技术部].maxSalary 20000.0); }断言在 Debug 下生效Release 下被忽略所以正式发布前要用 Debug 跑一遍全部测试。测试用例不用多覆盖“正常添加、重复添加、查找不存在、统计空列表、统计单元素”这几个边界就够了。6.3 一个我常用的调试习惯把关键操作写日志职工信息管理系统出问题时最有用的是知道“最后一步做了什么”。我会在增删改查的关键路径上加一行日志输出到stderr或者单独的日志文件#include ctime void log(const std::string msg) { std::time_t t std::time(nullptr); char buf[64]; std::strftime(buf, sizeof(buf), %Y-%m-%d %H:%M:%S, std::localtime(t)); std::cerr [ buf ] msg \n; }添加职工时log(add id std::to_string(e.getId()))删除时log(remove id ...)读取文件失败时log(read failed at line ...)。这些日志在排查“数据为什么丢了”“为什么查不到”时比断点还快。日志不要写太多关键路径各一行就够否则文件膨胀得比数据还快。6.4 交付前检查清单检查项通过标准空列表统计不崩溃平均薪资显示 0 或 N/A重复 id 添加返回失败不覆盖已有记录文件不存在时读取提示文件不存在不崩溃文件损坏行跳过并记录行号不中断整个读取排序后查找id 索引已重建查找结果正确删除后查找被删 id 查不到其他 id 正常薪资显示保留两位小数无浮点尾巴中文姓名保存后重新读取内容一致这张表是我每次交付前都会跑一遍的花不了十分钟但能挡掉八成“演示时翻车”的情况。职工信息管理系统本身不难难的是把边界情况一个个堵住。我自己的教训是别在第一次写完就急着加功能先把增删改查和文件读写跑通、跑稳再往上叠统计和排序。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

C#调用FFmpeg解码H.264裸流:从P/Invoke到BMP输出

C#调用FFmpeg解码H.264裸流:从P/Invoke到BMP输出

简介:针对在 C# 环境下解码 H.264 视频的常见开发需求,这份 demo 项目提供了基于 FFmpeg 开源库的可运行框架,适合具有一定 C# 基础、希望向流媒体或视频处理方向扩展的开发者。项目完整演示了如何通过 P/Invoke 与 FFmpeg 动态库交互&#x…

2026/10/16 20:10:39 阅读更多 →
从权重文件到推理结果:Qwen-2.5_1.5B_Instruct_rai_1.8.0_medusa_1.0_npu 模型构成与目录文件逐项详解

从权重文件到推理结果:Qwen-2.5_1.5B_Instruct_rai_1.8.0_medusa_1.0_npu 模型构成与目录文件逐项详解

【免费下载链接】Qwen-2.5_1.5B_Instruct_rai_1.8.0_medusa_1.0_npu 项目地址: https://ai.gitcode.com/hf_mirrors/amd/Qwen-2.5_1.5B_Instruct_rai_1.8.0_medusa_1.0_npu 点击查看 免费下载 想搞懂 Qwen-2.5 1.5B Instruct 模型包到底由哪些文件组成?…

2026/10/16 20:10:39 阅读更多 →
free-claude-code实战:用编程代理低成本写开源代码

free-claude-code实战:用编程代理低成本写开源代码

“free-claude-code”这个短语,第一眼很容易被人误解成什么破解资源或灰色渠道。我一开始也只是把它当作一个随手敲下的仓库名,后来越用越觉得它其实概括了一套很正经的方法论:用智能体式编程工具,去写免费、开源、属于自己的代码…

2026/10/16 20:10:39 阅读更多 →

最新新闻

多动作并行异步DDPG:选矿浮选智能决策模型工程化实践

多动作并行异步DDPG:选矿浮选智能决策模型工程化实践

简介:本资源是一篇发表于《控制与决策》2022年第8期的学术论文PDF,面向自动化、智能优化与流程工业领域的研究生、科研人员及工程技术人员,聚焦选矿过程运行指标的动态决策难题。针对传统深度确定性策略梯度(DDPG)算法…

2026/10/18 14:09:21 阅读更多 →
UVM验证环境自动生成工具:一键生成testbench与组件代码

UVM验证环境自动生成工具:一键生成testbench与组件代码

简介:这是一款面向数字芯片验证工程师的UVM环境自动化构建工具,专为降低SystemVerilog验证平台搭建门槛而设计,尤其适合初/中级验证人员及需快速迭代验证场景的团队。资源包共78个文件,含14个核心UVM SystemVerilog源码&#xff0…

2026/10/18 14:09:21 阅读更多 →
AI 接进办公文档后,为什么还是会读错?从结构保真到结果复核的实现链路

AI 接进办公文档后,为什么还是会读错?从结构保真到结果复核的实现链路

办公 AI 的常见误差,往往从模型看到文档之前就开始了:表格中的列名丢了,批注混进正文了,脚注里的限制条件被截断了。等模型接到一段看似完整的文本,它可能已经失去了判断业务含义所需的关系。 因此,可靠的…

2026/10/18 14:09:21 阅读更多 →
分割标签怎样正确叠加?VTK 离散色表、透明背景与类别一致性

分割标签怎样正确叠加?VTK 离散色表、透明背景与类别一致性

分割模型输出了正确类别,界面上却颜色错乱、边缘冒出新颜色,或者背景遮住整幅原图。这些问题可能发生在可视化层,与模型推理精度无关。标签叠加需要同时维护类别、空间几何与颜色表达。本文从只有三种标签的合成体出发,建立可以直…

2026/10/18 14:09:21 阅读更多 →
舰载高频地波雷达MATLAB仿真:K分布杂波建模与CFAR检测全流程

舰载高频地波雷达MATLAB仿真:K分布杂波建模与CFAR检测全流程

简介:这份舰载高频地波雷达MATLAB仿真工程包,面向电子信息、雷达工程与信号处理方向的本科生和初级研究者,解决从杂波环境构建到目标检测验证的整套仿真需求,可直接用于课程设计、毕业设计或基础科研复现。压缩包共22个文件&#…

2026/10/18 14:09:21 阅读更多 →
Java AI应用开发实战:框架停更后的技术选型与工程化路径

Java AI应用开发实战:框架停更后的技术选型与工程化路径

1. 一个框架停更引发的技术选型焦虑前几天在一个技术交流群里,有位做Java后端的兄弟抛出一个问题:“Spring AI Alibaba是不是停更了?我看仓库好久没动静了,Java搞AI这块是不是没戏了?”群里瞬间热闹起来,有…

2026/10/18 14:08:20 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/18 0:55:02 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →