数据结构大作业实战:教务管理系统从需求到验收的完整实现路径

简介:这份资源是华南理工大学数据结构课程的大作业完整实现——教务管理系统,面向正在学习数据结构、需要完成课程设计或想通过真实项目巩固理论的高校学生。系统围绕学籍与课程信息管理展开,将数组、链表、树、栈、队列、散列表等结构落地到实际功能中,例如用数组存储学生基本信息、用链表管理课程表、用搜索树高效检索课程与学生、用栈实现撤销注册、用队列模拟选课调度,并涉及文件读写以持久化数据。压缩包共56个文件,包含23个cpp源文件、20个头文件、9个txt测试数据与说明、3个可执行程序及1份doc报告,整体约1.92MB,教师端、学生端、教务员端三端代码与报告齐备。目前已有699人学习下载,适合对照源码理解数据结构选型、算法复杂度分析与模块协作方式,也可作为课程设计参考模板。

1. 教务管理系统大作业:从需求到验收的完整实现路径

每到学期中后段,数据结构大作业就成了不少同学的“玄学时刻”——题目看着都懂,真动手写起来却不知道从哪下手。教务管理系统这个题目尤其典型:它不像排序算法那样有标准答案,也不像链表操作那样边界清晰,而是要求你把线性表、查找、排序、文件存储这些知识点串成一个能跑起来的完整系统。我带过几届学生的课程设计,发现真正卡住大家的从来不是某个算法写不出来,而是不知道一个“合格”的教务管理系统应该包含哪些模块、数据怎么组织、功能怎么划分、验收时老师会盯着哪些点。这篇方案就按一个完整交付项目的思路,把需求分析、数据结构选型、模块实现、避坑要点和验收准备全部拆开讲清楚,适合正在做数据结构课程设计或大作业的同学直接参考。

2. 需求分析与数据结构选型:先想清楚存什么、怎么查

2.1 功能需求拆解:三类角色、六个核心模块

教务管理系统的需求看起来杂,但按角色拆开就清晰了。通常的做法是划分三类使用角色:管理员、教师、学生。管理员负责基础数据的增删改查和全局管理,教师负责成绩录入和查询,学生负责个人信息和成绩查看。围绕这三类角色,核心功能模块可以归纳为六个:

  • 学生信息管理:学号、姓名、性别、班级、专业等字段的录入、修改、删除、按条件查询
  • 教师信息管理:工号、姓名、所属院系、职称等字段的维护
  • 课程信息管理:课程编号、课程名称、学分、授课教师、上课时间地点
  • 选课管理:学生选课、退课,以及选课人数限制
  • 成绩管理:成绩录入、修改、按学生或课程查询、绩点计算
  • 统计与排序:按成绩排序、按学分统计、班级排名等

这六个模块不是拍脑袋定的,而是从“教务”这个场景的真实业务流里抽出来的。你写大作业时不需要全部实现,但至少要覆盖学生信息管理、课程管理、选课和成绩管理这四个,否则工作量撑不起一份完整的设计文档。

2.2 数据结构选型:为什么用顺序表加链表混合存储

很多同学一上来就纠结“到底用链表还是数组”,其实这个系统里不同实体的访问模式不一样,选型也应该不一样。我一般会这样分:

学生信息和课程信息用顺序表(数组)存储。原因很直接:这两类数据的规模相对固定,一个学校一个年级的学生数量不会频繁剧烈变化,而且最常用的操作是“按学号查找”和“遍历输出”,顺序表的随机访问特性正好匹配。用数组存,查找可以上二分,遍历也快。

选课记录用链表存储。选课关系是典型的多对多动态数据,一个学生可能选多门课,一门课可能有多个学生选,而且选课、退课操作频繁。链表的插入删除是O(1)(已知位置的前提下),比数组搬移元素高效得多。

成绩数据可以挂在选课记录节点上。每一条选课记录里附带一个成绩字段,这样查某个学生的所有成绩,只需要遍历该学生的选课链表;查某门课的所有成绩,遍历该课程的选课链表。不需要单独再建一张成绩表。

用代码表达一下核心结构:

// 学生信息节点——顺序表存储 typedef struct { char id[12]; // 学号,主键 char name[20]; // 姓名 char gender[4]; // 性别 char class_name[20];// 班级 char major[30]; // 专业 } Student; // 课程信息节点——顺序表存储 typedef struct { char course_id[10]; // 课程编号,主键 char course_name[30]; float credit; // 学分 char teacher_id[10];// 授课教师工号 int capacity; // 容量上限 int selected; // 已选人数 } Course; // 选课记录节点——链表存储 typedef struct SelectNode { char student_id[12]; char course_id[10]; float score; // 成绩,初始为-1表示未录入 struct SelectNode *next; } SelectNode;

这里的关键设计点是:学生和课程用数组存,选课用链表存,成绩作为选课记录的属性而不是独立实体。这样设计的好处是数据冗余少,一致性容易维护——退课时直接删节点,成绩自然跟着消失,不会出现“选了课但成绩表里还有孤儿记录”的情况。

2.3 查找与排序策略:二分查找加快速排序的组合

查找方面,按学号查学生是最频繁的操作。如果学生数组按学号有序,就可以用二分查找,时间复杂度O(log n)。但插入新学生时要维持有序,插入位置之后的元素需要后移,这是顺序表的固有代价。实际做的时候,我建议插入时先追加到末尾,查找前统一排一次序,或者维护一个“脏标记”,有插入操作就标记,下次查找前重新排序。这样比每次插入都搬移元素要实用。

排序方面,成绩排名用快速排序最合适。快排的平均时间复杂度是O(n log n),而且原地排序不需要额外空间。C语言里qsort可以直接用,但大作业通常要求手写,那就把快排的partition写清楚:

// 按成绩降序排列选课记录数组 int partition(SelectNode *arr[], int low, int high) { float pivot = arr[high]->score; // 以最后一个元素为基准 int i = low - 1; for (int j = low; j < high; j++) { // 降序:成绩高的排前面 if (arr[j]->score >= pivot) { i++; SelectNode *temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } SelectNode *temp = arr[i + 1]; arr[i + 1] = arr[high]; arr[high] = temp; return i + 1; }

这段代码里pivot选的是最后一个元素,实际项目中为了避免有序数据导致最坏情况O(n²),通常会随机选基准或者三数取中。大作业里如果数据量不大,直接用最后一个元素也能过,但设计文档里最好提一句“可优化基准选择策略”。

3. 总体架构与模块划分:三层结构怎么落地

3.1 分层设计:数据层、业务层、界面层的职责边界

一个能拿得出手的教务管理系统,代码不能全堆在main函数里。通常的做法是分三层:

数据层负责所有数据的存储和读写。包括结构体定义、全局数据数组、文件读写函数。这一层不关心业务逻辑,只提供“存进去”和“取出来”的能力。

业务层负责具体的功能实现。比如“添加学生”这个操作,业务层要检查学号是否重复、数组是否已满、然后调用数据层的插入函数。再比如“选课”,业务层要判断课程容量是否已满、学生是否已经选过这门课、然后创建选课记录节点。

界面层负责和用户交互。菜单显示、输入读取、结果输出都在这一层。界面层不直接操作数据,所有请求都通过调用业务层函数完成。

这样分的好处是:调试的时候可以单独测业务层,不用每次都走菜单;换界面(比如从控制台换成图形界面)时业务层不用动;写设计文档时层次清晰,老师一眼就能看出你是有架构意识的。

3.2 文件存储方案:用二进制文件做持久化

大作业通常要求数据能保存到文件,下次打开程序还能读出来。这里有个容易翻车的点:用文本文件存结构体,读写时要格式化解析,容易出错;用二进制文件直接fwrite整个结构体数组,简单但可读性差。

我的建议是:学生和课程用二进制文件整块读写,选课记录用文本文件按行存储。学生和课程是定长记录,二进制读写效率高;选课记录是动态链表,用文本文件每行一条记录,方便调试时直接打开看。

// 保存学生数据到二进制文件 void save_students(Student students[], int count) { FILE *fp = fopen("students.dat", "wb"); if (fp == NULL) { printf("文件打开失败\n"); return; } // 先写数量,再写数据块 fwrite(&count, sizeof(int), 1, fp); fwrite(students, sizeof(Student), count, fp); fclose(fp); } // 从二进制文件读取学生数据 int load_students(Student students[]) { FILE *fp = fopen("students.dat", "rb"); if (fp == NULL) return 0; // 文件不存在,返回0条记录 int count; fread(&count, sizeof(int), 1, fp); fread(students, sizeof(Student), count, fp); fclose(fp); return count; }

注意这里先写count再写数据块,读取时也先读count再读数据。这样即使结构体大小变了,只要读写用同一套结构体定义,就不会错位。选课记录的文本存储格式可以设计成学号 课程号 成绩每行一条,读取时用fscanf逐行解析。

3.3 菜单驱动的主控流程

界面层用菜单驱动是最稳妥的方案。主菜单列出所有功能,用户输入编号进入子菜单,子菜单执行完操作后返回主菜单。这种结构写起来直白,老师验收时也容易操作。

void main_menu() { int choice; while (1) { printf("\n===== 教务管理系统 =====\n"); printf("1. 学生信息管理\n"); printf("2. 课程信息管理\n"); printf("3. 选课管理\n"); printf("4. 成绩管理\n"); printf("5. 统计与排序\n"); printf("0. 退出系统\n"); printf("请选择:"); scanf("%d", &choice); switch (choice) { case 1: student_menu(); break; case 2: course_menu(); break; case 3: select_menu(); break; case 4: score_menu(); break; case 5: stats_menu(); break; case 0: save_all(); exit(0); default: printf("无效输入,请重新选择\n"); } } }

这个主控流程里,save_all()在退出前统一保存所有数据,避免每次操作都写文件影响性能。但要注意:如果程序异常退出(比如直接关窗口),数据会丢。更稳妥的做法是每次增删改操作后都立即保存,或者加一个“手动保存”菜单项。大作业里我一般建议每次修改后立即保存,虽然效率低一点,但不会丢数据。

4. 核心模块实现:选课、成绩与统计的代码落地

4.1 选课模块:链表插入与容量校验

选课是整系统里逻辑最复杂的模块,因为它涉及学生、课程、选课记录三方的状态同步。核心逻辑是:先检查学生是否存在、课程是否存在、课程是否已满、学生是否已选过,全部通过后才创建选课记录节点。

// 选课操作 int select_course(char *student_id, char *course_id) { // 1. 检查学生是否存在 int stu_idx = find_student_by_id(student_id); if (stu_idx == -1) { printf("学号不存在\n"); return 0; } // 2. 检查课程是否存在 int course_idx = find_course_by_id(course_id); if (course_idx == -1) { printf("课程编号不存在\n"); return 0; } // 3. 检查课程容量 if (courses[course_idx].selected >= courses[course_idx].capacity) { printf("该课程已满\n"); return 0; } // 4. 检查是否已经选过 if (is_selected(student_id, course_id)) { printf("已选过该课程,不能重复选课\n"); return 0; } // 5. 创建选课记录节点,头插法插入链表 SelectNode *node = (SelectNode *)malloc(sizeof(SelectNode)); strcpy(node->student_id, student_id); strcpy(node->course_id, course_id); node->score = -1; // -1表示成绩未录入 node->next = select_head; select_head = node; // 6. 更新课程已选人数 courses[course_idx].selected++; printf("选课成功\n"); return 1; }

这段代码里find_student_by_id和find_course_by_id是二分查找的实现,is_selected遍历选课链表检查是否已有记录。头插法插入链表是O(1)操作,不需要遍历到尾部。注意score初始化为-1,表示成绩未录入,后续成绩管理模块只处理score >= 0的记录。

4.2 成绩录入与绩点计算

成绩录入的逻辑是:找到对应的选课记录,修改score字段。如果成绩已经录入过,允许修改但要有提示。绩点计算通常按学校规则来,常见的是绩点 = (分数 - 50) / 10,低于60分绩点为0。

// 录入成绩 int input_score(char *student_id, char *course_id, float score) { if (score < 0 || score > 100) { printf("成绩必须在0-100之间\n"); return 0; } SelectNode *p = select_head; while (p != NULL) { if (strcmp(p->student_id, student_id) == 0 && strcmp(p->course_id, course_id) == 0) { if (p->score >= 0) { printf("该成绩已录入(%.1f),是否覆盖?(1是/0否):", p->score); int confirm; scanf("%d", &confirm); if (confirm != 1) return 0; } p->score = score; printf("成绩录入成功\n"); return 1; } p = p->next; } printf("未找到选课记录,请先选课\n"); return 0; } // 计算绩点 float calc_gpa(float score) { if (score < 60) return 0.0; return (score - 50) / 10.0; }

这里有个细节:成绩录入前必须确认选课记录存在。如果学生没选课就直接录成绩,数据就乱了。所以input_score里先遍历链表找记录,找不到就提示“请先选课”。这个校验逻辑在设计文档里要写清楚,验收时老师很可能会故意先录成绩再选课,看你的系统会不会出错。

4.3 统计排序:按成绩排名与学分统计

统计模块通常要求两个功能:按成绩排序输出和按学分统计。排序用快排,统计用遍历累加。

// 按课程输出成绩排名 void rank_by_course(char *course_id) { // 收集该课程的所有选课记录到数组 SelectNode *arr[MAX_RECORDS]; int n = 0; SelectNode *p = select_head; while (p != NULL) { if (strcmp(p->course_id, course_id) == 0 && p->score >= 0) { arr[n++] = p; } p = p->next; } if (n == 0) { printf("该课程暂无成绩记录\n"); return; } // 快速排序 quick_sort(arr, 0, n - 1); // 输出排名 printf("排名\t学号\t\t成绩\t绩点\n"); for (int i = 0; i < n; i++) { printf("%d\t%s\t%.1f\t%.2f\n", i + 1, arr[i]->student_id, arr[i]->score, calc_gpa(arr[i]->score)); } } // 统计某学生的总学分和平均绩点 void stats_student(char *student_id) { float total_credit = 0, total_gpa = 0; int count = 0; SelectNode *p = select_head; while (p != NULL) { if (strcmp(p->student_id, student_id) == 0 && p->score >= 0) { int idx = find_course_by_id(p->course_id); if (idx != -1) { total_credit += courses[idx].credit; total_gpa += calc_gpa(p->score); count++; } } p = p->next; } if (count == 0) { printf("该学生暂无成绩记录\n"); return; } printf("已修学分:%.1f\n", total_credit); printf("平均绩点:%.2f\n", total_gpa / count); }

rank_by_course先把链表里符合条件的节点指针收集到数组,再对数组排序,这样不改变链表本身的结构。stats_student遍历链表累加学分和绩点,最后算平均。这两个函数都不复杂,但要注意边界情况:没有记录时要有提示,不能直接除零。

5. 避坑与常见问题:那些年我们翻过的车

5.1 输入缓冲区残留导致菜单乱跳

现象:输入一个数字后按回车,下一个scanf直接跳过了,或者菜单连续打印两次。

原因:scanf读数字时遇到换行符会停止,但换行符还留在输入缓冲区里,下一个scanf("%c")或gets会直接读到这个换行符。

解决:在scanf后面加getchar()吃掉换行符,或者用scanf(" %c", &ch)(注意%c前面加空格)跳过空白字符。更彻底的做法是用fgets读整行再解析。

5.2 文件读写时结构体对齐导致数据错位

现象:保存到文件的数据,重新读取后字段值乱了,或者程序直接崩溃。

原因:C语言结构体有内存对齐机制,不同编译选项下sizeof(Student)可能不一样。如果写文件和读文件的程序用了不同的对齐设置,数据就会错位。

解决:读写用同一个可执行文件,不要分开编译。如果必须跨程序读写,用#pragma pack(1)强制1字节对齐,或者改用文本格式存储。

5.3 链表操作忘记更新头指针

现象:删除选课记录后,程序崩溃或者数据没删掉。

原因:删除链表节点时,如果删除的是头节点,需要更新select_head指针。很多同学只写了p->next = p->next->next,头节点的情况没处理。

解决:删除操作统一用带头节点的链表,或者单独处理头节点删除的情况。我一般建议加一个空的头节点(哨兵节点),这样所有删除操作逻辑一致,不用特判。

5.4 数组越界写入导致数据被覆盖

现象:添加学生后,其他学生的信息变了,或者程序行为异常。

原因:学生数组定义了固定大小(比如Student students[100]),添加时没有检查count < 100,直接写students[count++],越界写到了相邻内存。

解决:每次添加前检查count是否达到上限,达到就提示“系统容量已满”。同时把数组大小定义成宏,方便统一修改。

5.5 浮点数比较用==导致排序结果不稳定

现象:两个成绩相同的记录,排序后顺序随机变化,或者排名出现并列但显示不一致。

原因:浮点数在计算机里是近似存储的,0.1 + 0.2 != 0.3。用==比较两个float可能得到意外结果。

解决:比较浮点数时用差值绝对值小于一个极小值(比如1e-6)来判断相等。排序时如果成绩相同,可以按学号二次排序,保证结果稳定。

6. 验收与答辩:怎么让老师一眼看到你的设计亮点

验收和答辩不是把程序跑一遍就完事,老师看的是你有没有“设计意识”。我一般会让学生准备三样东西:一份功能演示脚本、一份数据结构说明图、一份测试用例表。

功能演示脚本要按“正常流程→边界情况→异常输入”的顺序走。正常流程就是添加学生、添加课程、选课、录成绩、查排名,一气呵成。边界情况包括:选课人数刚好达到容量上限、成绩刚好60分、学生没有任何选课记录。异常输入包括:输入不存在的学号、重复选课、成绩输入负数。你把这些都演示一遍,老师就知道你的系统是经过测试的,不是“能跑就行”。

数据结构说明图不用画得多漂亮,但要把学生数组、课程数组、选课链表三者的关系画清楚。用方框表示结构体,用箭头表示指针,标注清楚主键和外键。老师一看图就知道你理解了自己写的数据结构,而不是抄来的。

测试用例表可以做成这样:

测试项输入预期输出实际结果
添加重复学号学号已存在提示“学号重复”一致
选课容量已满选第101个提示“课程已满”一致
成绩录入超范围输入150提示“成绩无效”一致
查询无选课学生学号无记录提示“暂无成绩”一致

这张表在答辩时直接展示,比你说一百句“我测试过了”都管用。

答辩时老师最常问的几个问题,提前准备好答案:为什么选链表不选数组(答:选课记录动态变化,链表插入删除O(1));文件存储怎么保证一致性(答:退出时统一保存,或者每次修改立即保存);排序算法的时间复杂度(答:快排平均O(n log n),最坏O(n²),可以通过随机基准优化)。还有一个高频问题:“如果学生人数超过数组容量怎么办?”——这时候你要能说出“当前是静态数组,扩展方案是改成动态数组,用realloc扩容,或者直接用链表存学生”。

从那以后我每次带课程设计,都要求学生先写测试用例再写代码,测试用例过了才算完成。这个习惯看起来多花时间,实际上省下了大量调试的功夫。希望这份方案能帮你把教务管理系统这个大作业理清楚,从需求到验收一路走通。

本文还有配套的精品资源,点击获取

相关新闻

lingbot-map:机器人地图管理模块的设计与工程实践

lingbot-map:机器人地图管理模块的设计与工程实践

做机器人导航落地项目时&#xff0c;很多人都会先踩一遍同一个坑&#xff1a;建图、定位、导航全写在一个模块里&#xff0c;跑到第二间办公室就开始改不动。今天想分享的是我项目中一个很小的自研模块——lingbot-map&#xff0c;它专门负责机器人地图管理这件事。这个模块只做…

2026/10/22 11:00:21 阅读更多 →
WebDAVClient安卓编译指南:Kotlin 1.8.20+AGP 8.1+Gradle 8.1黄金三角配置

WebDAVClient安卓编译指南:Kotlin 1.8.20+AGP 8.1+Gradle 8.1黄金三角配置

简介&#xff1a;WebDAVClient是一款基于Kotlin开发的轻量级Android端WebDAV协议客户端&#xff0c;面向Android开发者及需要在移动设备上高效管理远程文件的技术人员&#xff0c;解决跨平台访问NAS、私有云或企业文档服务器等WebDAV服务时缺乏原生支持的问题。资源包共149个文…

2026/10/21 6:30:36 阅读更多 →
迭代器模式实战:告别索引遍历,给数据装个自动导航

迭代器模式实战:告别索引遍历,给数据装个自动导航

前阵子接了一个内部小项目的维护&#xff0c;代码里有一段遍历逻辑&#xff0c;写得极其辛苦&#xff1a;外层是一个 ArrayList&#xff0c;内层还有两个 Map&#xff0c;为了把数据拼成报表&#xff0c;写了三层循环&#xff0c;索引变量从 i、j 到 k&#xff0c;中间还穿插各…

2026/10/22 10:39:49 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年&#xff0c;我大部分时间都在跟浏览器标签页打交道&#xff0c;直到第一次把桌面应用跑起来&#xff0c;才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词&#xff0c;最开始是在某段时间频繁出现在同事的讨论里&#xff0c;一个用HTML…

2026/10/22 10:18:38 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档&#xff0c;主要面向智能锁安装人员、终端用户及售后维护者&#xff0c;帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件&#xff0c;大小4.37MB&#xff0c;内容结构清晰&#xff…

2026/10/22 11:01:53 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统&#xff0c;整车要求空载跑到8m/s&#xff0c;电机转速已经拉到额定点&#xff0c;驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令&#xff0c;转速纹丝不动&#xff0c;三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/22 9:44:47 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年&#xff0c;用它写过嵌入式驱动、做过游戏服务端&#xff0c;也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词&#xff0c;我其实挺感慨的——这门语言的难点从来不是语法多&#xff0c;而是知识点之间的耦合太深…

2026/10/22 10:42:00 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书以PDF格式发布&#xff0c;适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开&#xff0c;先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能&#xff0c;再给出完整安装步骤&…

2026/10/22 10:40:08 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历&#xff1a;翻开源码注释、论文摘要或者一份专业报告&#xff0c;每个字都认识&#xff0c;连在一起却像天书。想找人聊聊&#xff0c;身边要么没人懂&#xff0c;要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型&#xff0c;几秒钟之后&a…

2026/10/22 10:56:37 阅读更多 →

日新闻

周新闻

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

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

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

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

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

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

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

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

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

2026/10/22 5:12:39 阅读更多 →

月新闻

我发现了一个新思路:用 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/21 21:50:56 阅读更多 →
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/21 21:51:55 阅读更多 →
黑夜航拍船只数据集训练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/21 16:24:48 阅读更多 →