三.Linux开发:通讯录(结构体实现)
本项目基于C 语言 单向链表实现通讯录管理系统采用分层架构设计支持人员信息增删改查、文件持久化存储配套完整的调试与 BUG 排查方案是 Linux C 开发入门的经典工程实践项目。完整代码在最下面。一、项目总览与架构设计1.1 核心需求分析通讯录系统的核心功能围绕联系人信息管理展开基础需求如下增添加新联系人支持姓名、手机号、性别、年龄等信息录入删按指定条件姓名 / 手机号删除联系人改修改已有联系人的信息查按姓名 / 手机号查询并展示联系人详情遍历格式化展示所有联系人列表持久化程序退出时保存数据到文件启动时自动加载数据交互控制台菜单支持用户选择操作1.2 分层架构设计项目采用经典的三层架构实现数据、逻辑、接口解耦提升代码可维护性与可调试性。层级职责特点数据层链表层定义数据结构实现链表基础操作增删节点、遍历、销毁只负责数据存储与组织不包含任何业务规则接口层API 层封装链表底层操作向上提供统一的函数接口屏蔽指针细节业务层无需直接操作链表节点业务逻辑层处理业务规则如数据合法性校验、重复判断、异常分支处理核心业务规则都在这一层实现交互层UI 层菜单打印、用户输入接收、结果展示只负责交互不包含核心逻辑架构设计的核心优势分层解耦修改链表实现不影响业务逻辑修改业务规则不改动底层数据结构便于调试问题可快速定位到对应层级可扩展性强后续新增功能只需在对应层级补充代码二、底层链表实现2.1 核心结构体定义1联系人信息结构体存储单个联系人的所有属性作为链表节点的数据域。typedef struct Contact { char name[32]; // 姓名 char phone[20]; // 手机号 char gender[8]; // 性别 int age; // 年龄 }Contact;2链表节点结构体单向链表节点包含数据域和指针域。// 链表节点结构体 typedef struct Node { Contact data; // 数据域联系人信息 struct Node* next; // 指针域指向后继节点 } Node;3链表管理结构体封装链表头指针与节点数量简化操作。// 通讯录链表管理结构体 typedef struct AddressBook { Node* head; int count; } AddressBook;2.2 链表基础操作函数数据层仅实现最基础的链表原子操作不包含业务判断init_book()初始化通讯录创建空链表头指针置 NULL计数清 0create_node(Contact data)申请内存创建新节点返回节点指针insert_head(Node **head, Node *new_node)头插法插入节点insert_tail(Node **head, Node *new_node)尾插法插入节点通讯录推荐使用保持添加顺序free_node(Node *node)释放单个节点内存destroy_book(Node **head)销毁整个链表释放所有节点内存防止内存泄漏关键注意点每次malloc后必须判断返回值是否为 NULL处理内存分配失败的情况尾节点的next必须初始化为NULL避免遍历出现野指针程序退出前必须遍历释放所有节点杜绝内存泄漏三、接口层设计与实现3.1 接口层的作用与设计原则接口层是业务逻辑与底层链表之间的桥梁核心作用是封装底层细节提供标准化调用入口。设计原则入参校验所有接口先判断参数合法性如指针非空、字符串长度合法状态返回函数返回状态码0 成功-1 失败-2 不存在等便于上层处理屏蔽指针业务层无需操作Node*只通过接口函数传递数据3.2 核心接口函数定义// 添加联系人传入联系人数据返回状态码 int api_add_contact(AddressBook *book, Contact *data); ​ // 删除联系人按姓名删除返回状态码 int api_delete_contact(AddressBook *book, const char *name); ​ // 查询联系人按姓名查找返回找到的节点数据通过出参带回 int api_search_contact(AddressBook *book, const char *name, Contact *result); ​ // 修改联系人按姓名查找并更新信息 int api_modify_contact(AddressBook *book, const char *name, Contact *new_data); ​ // 遍历所有联系人回调函数方式/直接打印 int api_list_all(AddressBook *book); ​ // 获取联系人总数 int api_get_count(AddressBook *book);四、业务逻辑层分析与实现4.1 业务层职责业务层是系统的核心负责所有业务规则判断调用接口层完成数据操作。数据合法性校验业务规则判断如姓名是否重复异常场景处理多步操作封装4.2 核心业务逻辑实现1添加联系人业务逻辑校验输入数据姓名不能为空、手机号长度合法、年龄在合理范围0~150查重判断调用查询接口检查姓名 / 手机号是否已存在调用接口层api_add_contact完成插入返回执行结果给交互层2删除联系人业务逻辑校验删除条件姓名非空判断链表是否为空空链表直接返回 “无数据”调用接口层执行删除根据返回值反馈 “删除成功 / 联系人不存在”3修改联系人业务逻辑先查询目标联系人是否存在校验新数据的合法性调用接口层执行修改4查询与遍历业务逻辑查询支持精确查询也可扩展模糊查询遍历格式化输出对齐列宽提升可读性五、人员操作功能调试与运行5.1 编译与调试环境编译命令gcc -g contact.c main.c -o contact_book-g参数生成调试信息支持 gdb 调试调试工具Linux 下使用gdbWindows 下可使用 VS、Dev-C 等 IDE 调试5.2 增改查功能调试要点添加功能调试断点位置create_node、insert_tail函数入口检查项节点内存是否分配成功、数据是否正确拷贝、next 指针是否置 NULL、头指针是否正确更新常见问题字符串赋值用了导致地址赋值错误必须用strcpy/strncpy查询功能调试断点位置遍历循环处、字符串比较处检查项循环是否遍历所有节点、字符串比较是否使用strcmp不能用常见问题遍历提前终止、未处理空链表情况修改功能调试检查项找到节点后数据是否正确覆盖、未找到节点是否返回对应错误码5.3 基础功能测试用例测试场景预期结果正常添加 1 条联系人添加成功总数 1添加姓名重复的联系人提示已存在添加失败空链表查询 / 删除提示无数据不崩溃修改不存在的联系人提示联系人不存在输入非法数据空姓名、负数年龄校验不通过提示重新输入六、删除功能调试与 BUG 解决方案链表删除是最高频出 BUG 的环节必须分场景处理。6.1 链表删除的三种场景删除头节点特殊处理将链表头指针指向第二个节点删除中间节点找到前驱节点prev执行prev-next cur-next删除尾节点前驱节点的next置为NULL6.2 常见 BUG 与排查方法写完代码可以查一下自己出现了哪些错误。常见 BUG现象原因解决方案段错误Segmentation Fault删除操作时程序崩溃空链表直接操作、访问 NULL 指针的 next函数入口先判空所有指针访问前校验非空删除头节点后数据丢失删除第一个人后链表无法遍历未更新头指针头指针变成野指针删除头节点时执行*head cur-next删除后遍历死循环执行删除后遍历停不下来删除尾节点时前驱节点 next 未置 NULL尾节点删除后手动将prev-next NULL明明存在却删不掉输入正确姓名但提示不存在字符串比较用了比较的是地址而非内容使用strcmp(name, cur-data.name) 0判断相等内存泄漏多次增删后内存占用升高删除节点只改指针未 free 节点内存移除节点后必须执行free(cur)释放内存删错节点删除的不是目标联系人遍历查找逻辑错误、指针偏移出错gdb 逐步打印节点姓名跟踪指针走向BUG 排查通用思路分段打印在关键节点打印指针地址、节点数据缩小问题范围gdb 单步执行跟踪每一步指针变化定位出错的代码行边界优先优先测试空链表、单节点链表、尾节点等边界场景七、文件持久化保存与加载7.1 接口层文件读写接口1保存文件接口遍历链表将每个节点的数据写入文件推荐二进制存储读写效率高、结构体直接读写。// 接口层保存通讯录到文件 int api_save_to_file(AddressBook *book, const char *filename) { FILE *fp fopen(filename, wb); // 二进制写模式 if(fp NULL) return -1; Node* cur book-head; while(cur ! NULL) { fwrite(cur-data, sizeof(Contact), fp); // 写入单条联系人数据 cur cur-next; } fclose(fp); return 0; }2加载文件接口从文件循环读取数据创建节点插入链表重建内存中的数据结构。// 接口层从文件加载通讯录 int api_load_from_file(AddressBook *book, const char *filename) { FILE* fp fopen(filename, rb); // 二进制读模式 if(fp NULL) return -1; // 文件不存在时返回初始化空链表 Contact tmp; while(fread(tmp, sizeof(Contact), 1, fp) 1) { api_add_contact(book, tmp); // 调用已有添加接口插入链表 } fclose(fp); return 0; }7.2 业务层持久化逻辑封装启动自动加载程序初始化时自动调用加载函数读取本地文件退出自动保存用户选择 “退出” 选项时自动执行保存操作手动保存菜单提供 “保存” 选项支持随时手动存档7.3 边界与异常处理文件不存在首次运行无数据文件时正常初始化空通讯录不报错文件为空读取 0 条数据返回空链表读写权限不足fopen失败时给出明确提示数据损坏可扩展校验逻辑异常文件提示数据损坏八、项目整体联调与运行8.1 完整运行流程程序启动 ↓ 初始化通讯录结构体 ↓ 加载本地数据文件 → 无文件则创建空通讯录 ↓ 打印主菜单等待用户输入 ↓ 用户选择功能 → 执行业务逻辑 → 展示结果 ↓ 循环菜单直到用户选择退出 ↓ 自动保存数据到文件 ↓ 释放链表所有内存 → 程序退出8.2 全场景测试用例首次运行测试无数据文件程序正常启动添加数据后退出再打开数据不丢失边界数据测试0 个联系人、1 个联系人、大量联系人100 条异常输入测试菜单输入字母、超长字符串输入程序不崩溃异常退出测试强制关闭程序后下次启动保留最后一次保存的数据重复操作测试反复增删改查链表结构正常无内存泄漏8.3 内存与健壮性优化内存泄漏检测使用valgrind工具检测命令valgrind --leak-checkfull ./contact_book要求程序正常退出后所有堆内存都被释放输入健壮性限制输入字符串长度使用fgets替代scanf避免缓冲区溢出错误提示友好所有失败操作给出明确原因不输出无意义的报错完整代码address_book.c#include stdio.h #include stdlib.h #include string.h ​ /************************* 宏定义 *************************/ #define NAME_LEN 32 #define PHONE_LEN 20 #define GENDER_LEN 8 #define DATA_FILE contact.dat ​ /************************* 数据结构定义 *************************/ // 联系人信息结构体数据域 typedef struct { char name[NAME_LEN]; char phone[PHONE_LEN]; char gender[GENDER_LEN]; int age; } Contact; ​ // 链表节点结构体 typedef struct Node { Contact data; // 数据域 struct Node* next; // 指针域指向后继节点 } Node; ​ // 通讯录管理结构体封装头指针与数量 typedef struct { Node* head; // 链表头指针 int count; // 当前联系人总数 } AddressBook; ​ /************************* 数据层链表基础操作 *************************/ /** * brief 初始化空通讯录 */ void init_book(AddressBook *book) { book-head NULL; book-count 0; } ​ /** * brief 创建新的链表节点 * param data 联系人数据 * return 新节点指针失败返回NULL */ Node* create_node(Contact *data) { Node *new_node (Node*)malloc(sizeof(Node)); if(new_node NULL) { printf(内存分配失败\n); return NULL; } // 拷贝数据初始化指针 memcpy(new_node-data, data, sizeof(Contact)); new_node-next NULL; return new_node; } ​ /** * brief 头插法插入节点 * return 0成功 -1失败 */ int insert_head(AddressBook *book, Node *new_node) { if(book NULL || new_node NULL) return -1; // 空链表新节点直接作为头节点 if(book-head NULL) { book-head new_node; } else { new_node-next book-head-next; book-head-next new_node; } book-count ; return 0; } ​ /** * brief 销毁整个链表释放所有内存防止内存泄漏 */ void destroy_book(AddressBook *book) { if(book NULL) return ; Node *cur book-head; while(cur ! NULL) { Node *tmp cur-next; free(cur); cur tmp; } book-head NULL; book-count 0; } ​ /************************* 接口层功能封装 *************************/ /** * brief 添加联系人接口 * return 0成功 -1失败 */ int api_add_contact(AddressBook *book, Contact *data) { if(book NULL || data NULL) return -1; Node *new_node create_node(data); if(new_node NULL) return -1; return insert_head(book, new_node); } ​ /** * brief 按姓名删除联系人接口 * return 0成功 -1参数/空链表错误 -2联系人不存在 */ int api_delete_contact(AddressBook *book, const char *name) { if(book NULL || name NULL || book-head NULL) return -1; Node *prev NULL; Node *cur book-head; // 遍历查找目标联系人 while(cur ! NULL) { if (strcmp(cur-data.name, name) 0) { break; } prev cur; cur cur-next; } if(cur NULL) return -2; // 未找到 // 执行删除分场景处理 if(prev NULL) { // 场景1删除头节点 book-head cur-next; } else { // 场景2删除中间/尾节点 prev-next cur-next; } free(cur); book-count--; return 0; } ​ /** * brief 按姓名查询联系人 * param result 出参带回找到的联系人数据 * return 0成功 -1未找到 */ int api_search_contact(AddressBook *book, const char *name, Contact *result) { if(book NULL || name NULL || result NULL) return -1; Node *cur book-head; while(cur ! NULL) { if(strcmp(cur-data.name, name) 0) { memcpy(result, cur-data, sizeof(Contact)); return 0; } cur cur-next; } return -1; } ​ /** * brief 修改联系人信息 * return 0成功 -1失败 */ int api_modify_contact(AddressBook *book, const char *name, Contact *new_data) { if (book NULL || name NULL || new_data NULL) return -1; Node *cur book-head; while(cur ! NULL) { if(strcmp(cur-data.name, name) 0) { // 保留原姓名更新其他字段 strncpy(cur-data.phone, new_data-phone, PHONE_LEN - 1); strncpy(cur-data.gender, new_data-gender, GENDER_LEN - 1); return 0; } cur cur-next; } return -1; } ​ /** * brief 遍历并打印所有联系人 */ void api_list_all(AddressBook *book) { if (book NULL || book-head NULL) { printf(通讯录为空暂无联系人\n); return ; } printf(\n 联系人列表共%d条\n, book-count); printf(%-12s %-15s %-6s %-4s\n, 姓名, 手机号, 性别, 年龄); printf(----------------------------------------\n); Node *cur book-head; while(cur ! NULL) { printf(%-12s %-15s %-6s %-4d\n, cur-data.name, cur-data.phone, cur-data.gender, cur-data.age); cur cur-next; } printf(\n); } ​ /** * brief 保存通讯录到文件 * return 0成功 -1失败 */ int api_save_to_file(AddressBook *book, const char *filename) { if (book NULL || filename NULL) return -1; FILE *fp fopen(filename, wb); // 二进制写模式 if(fp NULL) { perror(保存文件失败); return -1; } Node *cur book-head; while(cur ! NULL) { fwrite(cur-data, sizeof(Contact), 1, fp); cur cur-next; } fclose(fp); return 0; } ​ /** * brief 从文件加载通讯录 * return 0成功 -1文件不存在/读取失败 */ int api_load_from_file(AddressBook *book, const char *filename) { if (book NULL || filename NULL) return -1; FILE *fp fopen(filename, rb); if (fp NULL) { // 文件不存在属于正常情况首次运行不报错 return -1; } Contact temp; while(fread(temp, sizeof(Contact), 1, fp) 1) { api_add_contact(book, temp); } fclose(fp); return 0; } ​ /************************* 业务逻辑层 *************************/ /** * brief 校验联系人数据合法性 * return 1合法 0非法 */ int biz_validate_contact(Contact *data) { if (data NULL) return 0; if (strlen(data-name) 0) return 0; // 姓名不能为空 if (data-age 0 || data-age 150) return 0; // 年龄范围校验 if (strlen(data-phone) 0) return 0; // 手机号不能为空 return 1; } ​ /** * brief 添加联系人业务逻辑查重 校验 调用接口 * return 0成功 -1数据非法 -2姓名重复 */ int biz_add_contact(AddressBook *book, Contact *data) { // 1. 数据合法性校验 if (!biz_validate_contact(data)) { return -1; } // 2. 姓名查重 Contact tmp; if (api_search_contact(book, data-name, tmp) 0) { return -2; } // 3. 调用接口层执行添加 return api_add_contact(book, data); } ​ /************************* 交互层菜单与工具函数 *************************/ // 清空输入缓冲区避免scanf残留换行影响后续输入 void clear_input_buffer() { int c; while((c getchar())! \n c ! EOF); } ​ // 打印主菜单 void print_menu() { printf(\n 通讯录管理系统 \n); printf(1. 添加联系人\n); printf(2. 删除联系人\n); printf(3. 修改联系人\n); printf(4. 查询联系人\n); printf(5. 查看所有联系人\n); printf(6. 保存数据到文件\n); printf(0. 退出系统\n); printf(\n); printf(请输入选项); } ​ // 录入联系人信息 void input_contact(Contact *data) { printf(请输入姓名); scanf(%s, data-name); printf(请输入手机号); scanf(%s, data-phone); printf(请输入性别); scanf(%s, data-gender); printf(请输入年龄); scanf(%d, data-age); clear_input_buffer(); } ​ /************************* 主函数程序入口 *************************/ int main() { AddressBook book; init_book(book); // 启动自动加载本地数据 api_load_from_file(book, DATA_FILE); printf(系统启动完成已加载%d条联系人数据\n, book.count); int choice -1; char name_buf[NAME_LEN]; Contact tmp_data; while(1) { print_menu(); scanf(%d, choice); clear_input_buffer(); switch(choice) { case 1: // 添加联系人 printf(\n--- 添加联系人 ---\n); input_contact(tmp_data); int ret biz_add_contact(book, tmp_data); if (ret 0) { printf(添加成功\n); } else if (ret -1) { printf(添加失败数据不合法\n); } else if (ret -2) { printf(添加失败该姓名已存在\n); } break; case 2: // 删除联系人 printf(\n--- 删除联系人 ---\n); printf(请输入要删除的姓名); scanf(%s, name_buf); clear_input_buffer(); ret api_delete_contact(book, name_buf); if (ret 0) { printf(删除成功\n); } else if (ret -2) { printf(删除失败联系人不存在\n); } else { printf(删除失败\n); } break; case 3: // 修改联系人 printf(\n--- 修改联系人 ---\n); printf(请输入要修改的姓名); scanf(%s, name_buf); clear_input_buffer(); if (api_search_contact(book, name_buf, tmp_data) ! 0) { printf(联系人不存在\n); break; } printf(请输入新的信息姓名不可修改\n); printf(新手机号); scanf(%s, tmp_data.phone); printf(新性别); scanf(%s, tmp_data.gender); printf(新年龄); scanf(%d, tmp_data.age); clear_input_buffer(); ​ if (api_modify_contact(book, name_buf, tmp_data) 0) { printf(修改成功\n); } else { printf(修改失败\n); } break; case 4: // 查询联系人 printf(\n--- 查询联系人 ---\n); printf(请输入要查询的姓名); scanf(%s, name_buf); clear_input_buffer(); if (api_search_contact(book, name_buf, tmp_data) 0) { printf(\n查询结果\n); printf(姓名%s\n, tmp_data.name); printf(手机号%s\n, tmp_data.phone); printf(性别%s\n, tmp_data.gender); printf(年龄%d\n, tmp_data.age); } else { printf(未找到联系人\n); } break; case 5: // 查看所有 api_list_all(book); break; case 6: // 手动保存 if (api_save_to_file(book, DATA_FILE) 0) { printf(数据已保存到 %s\n, DATA_FILE); } break; case 0: // 退出 printf(\n正在保存数据...\n); api_save_to_file(book, DATA_FILE); destroy_book(book); // 释放内存 printf(系统已退出欢迎下次使用\n); return 0; default: printf(输入无效请输入0-6之间的数字\n); break; } } return 0; }

相关新闻

2026Python内存优化实战教程:布尔数组从1MB到100KB,从入门到精通

2026Python内存优化实战教程:布尔数组从1MB到100KB,从入门到精通

做Python开发,存大量布尔值的场景太常见了:线性筛素数、用户标签、特征工程标记、布隆过滤器、位图索引,数据量一上来内存直接爆,list占内存大,numpy不够灵活,自己写位数组又麻烦。这篇是2026年最新的Pytho…

2026/7/30 5:24:20 阅读更多 →
介观电子输运:从量子效应到纳米器件设计的核心原理

介观电子输运:从量子效应到纳米器件设计的核心原理

介观系统中的电子输运,这个看似专业的物理概念,实际上正在深刻改变我们对纳米尺度电子行为的理解。如果你正在研究纳米器件、量子计算或低维材料,却对传统宏观输运理论与实际观测结果之间的差距感到困惑,那么这篇文章将为你揭示其…

2026/7/30 5:24:20 阅读更多 →
短信炸弹与越权提权组合攻击:原理、渗透测试与纵深防御实战

短信炸弹与越权提权组合攻击:原理、渗透测试与纵深防御实战

1. 项目概述:当“短信炸弹”遇上“越权提权”最近在给一家金融科技公司做安全评估时,我们遇到了一个非常典型的组合攻击场景:攻击者利用一个看似无害的“短信验证码接口”,配合一个隐蔽的权限绕过漏洞,差点就拿到了核心…

2026/7/30 5:24:20 阅读更多 →

最新新闻

索尼FE 70-200mm f/2.8 GM II评测:轻量化远摄镜头的全面革新

索尼FE 70-200mm f/2.8 GM II评测:轻量化远摄镜头的全面革新

如果你是一位专业摄影师,最近正在为索尼全画幅微单系统挑选一支"万金油"远摄变焦镜头,那么索尼FE 70-200mm f/2.8 GM II(型号SEL70200G2)这个名字一定反复出现在你的备选清单中。作为索尼G大师镜头家族中最重要的专业级…

2026/7/30 5:31:23 阅读更多 →
OLAP 数据库混进 OLTP 链路:一次 ClickHouse 拖死 API 101 分钟的复盘

OLAP 数据库混进 OLTP 链路:一次 ClickHouse 拖死 API 101 分钟的复盘

📝 摘要:OLAP 数据库 ClickHouse 被"试验性"接入 OLTP 主链路,一次普通发版将其引爆:CK 磁盘满且无告警导致查询 hang,Spring Boot /actuator/health 每秒 480 次心跳逐个 ping 依赖借走 CK 连接,HikariCP 连接池 10 连接被 374 线程争抢耗尽,TCP 连接数从…

2026/7/30 5:31:23 阅读更多 →
堆优化Dijkstra算法详解:从稀疏图挑战到洛谷P4779模板实战

堆优化Dijkstra算法详解:从稀疏图挑战到洛谷P4779模板实战

1. 项目概述:从一道题到一套方法论如果你正在准备算法竞赛,或者在学习数据结构与算法的路上,那么“单源最短路径”绝对是一个绕不开的经典问题。而洛谷上的P4779这道题,被冠以“【模板】”之名,其地位不言而喻——它几…

2026/7/30 5:31:23 阅读更多 →
C++实战:从零构建文字冒险游戏“骗子酒馆”的完整指南

C++实战:从零构建文字冒险游戏“骗子酒馆”的完整指南

1. 项目概述:从“骗子酒馆”到C实战演练 最近在社区里看到不少朋友在讨论用C做些有趣的小项目来练手,从经典的贪吃蛇、俄罗斯方块,到一些需要点算法和设计模式支撑的复杂游戏。今天我想分享一个我个人觉得特别有意思的练手项目——“骗子酒馆…

2026/7/30 5:31:23 阅读更多 →
Harris角点检测算法原理与Matlab实战实现指南

Harris角点检测算法原理与Matlab实战实现指南

在图像处理与计算机视觉项目中,角点检测一直是基础且关键的技术环节。无论是做图像匹配、目标跟踪还是三维重建,Harris角点检测算法都因其稳定性和高效性成为首选方案之一。很多开发者在实际应用时,往往卡在参数调优和效果验证环节&#xff0…

2026/7/30 5:31:23 阅读更多 →
【系列:CCG Crypto CrackMe 逆向全解析 · 第 1 篇】

【系列:CCG Crypto CrackMe 逆向全解析 · 第 1 篇】

导读: 2001 年,CCG(China Cracking Group)的 Blowfish 放出了一个 CrackMe,声称"本题多解"。这个系列将完整记录破解它的全过程——从最基础的字节解析,到自定义壳的算法复原,到最后跑…

2026/7/30 5:30:22 阅读更多 →

日新闻

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:13 阅读更多 →
如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经在浏览…

2026/7/30 0:00:13 阅读更多 →
“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

更多请点击: https://intelliparadigm.com 第一章:AI 教师备课辅助 AI 教师备课辅助系统正逐步成为教育数字化转型的核心支撑工具,它并非替代教师,而是通过语义理解、知识图谱与多模态生成能力,将教师从重复性劳动中解…

2026/7/30 0:00:13 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/29 22:18:20 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻