结构体与函数:从数据封装到模块化编程的核心实践
1. 从“数据孤岛”到“智能单元”为什么我们需要结构体与函数如果你刚开始接触编程可能会觉得“结构体”和“函数”是两个独立的概念一个管数据打包一个管逻辑封装。但当你真正开始写一个稍微复杂点的项目比如用STM32控制一个机器人或者用Python处理一份包含用户姓名、年龄、地址的表格数据时你就会发现把它们分开用代码很快就会变得一团糟。想象一下你要管理一个班级的学生信息。没有结构体你可能需要这样char* student1_name 张三; int student1_age 18; float student1_score 95.5; char* student2_name 李四; int student2_age 19; float student2_score 88.0; // ... 更多学生每新增一个学生你就得手动声明三个独立的变量它们之间只有名字上的微弱关联。如果你想写一个函数来打印某个学生的信息你得把三个变量都传进去printStudent(student1_name, student1_age, student1_score)。这太容易出错了万一传错了顺序或者漏了一个bug就来了。这就是“数据孤岛”。而结构体就是来解决这个问题的。它像一个智能的收纳盒把逻辑上属于一个整体的数据打包在一起。上面的例子用结构体可以这样写struct Student { char name[50]; int age; float score; }; struct Student student1 {张三, 18, 95.5}; struct Student student2 {李四, 19, 88.0};现在一个学生的所有信息被封装在student1这个“盒子”里。数据不再是孤立的它们有了一个共同的家。那函数呢函数是行为的封装。继续上面的例子打印学生信息的函数现在清爽多了void printStudent(struct Student stu) { printf(姓名%s 年龄%d 分数%.1f\n, stu.name, stu.age, stu.score); }你只需要传递一个结构体变量stu函数就能访问其内部所有成员。这不仅仅是代码变短了更重要的是它建立了一种清晰的契约这个函数就是用来处理Student这种数据类型的。所以结构体与函数的结合其核心价值在于创建高内聚、低耦合的代码单元。结构体定义了“是什么”数据模型函数定义了“能做什么”行为操作。两者结合就能构建出模拟现实世界实体的“智能对象”雏形。这对于任何想要编写可维护、可扩展、逻辑清晰代码的程序员来说都是必须掌握的基本功。无论你是做嵌入式开发如STM32 HAL库中大量的结构体配置函数还是进行数据分析如Pandas的DataFrame本质上就是高级结构体其str、groupby等都是函数这个组合拳都是你的核心工具。2. 结构体不仅仅是数据的集装箱很多人把结构体理解成“变量打包”这没错但只看到了第一层。在实际开发中结构体的设计直接影响着程序的效率、内存布局乃至整个架构的清晰度。2.1 定义与初始化打好地基定义结构体就是蓝图设计。以C语言为例// 定义一个传感器数据的结构体 struct SensorData { uint32_t timestamp; // 时间戳 int16_t raw_value; // 原始ADC值 float filtered_value; // 滤波后的值 uint8_t sensor_id; // 传感器ID bool is_valid; // 数据是否有效 };这里有几个关键点成员选择哪些数据应该放在一起原则是“高内聚”。SensorData里的所有成员都共同描述一次传感器采样事件。如果把不相关的“设备IP地址”也塞进来就破坏了内聚性。类型选择int16_t、uint32_t这些定宽类型来自stdint.h在嵌入式开发中至关重要它能确保在不同平台上的数据长度一致。bool类型需要C99或以上标准支持。命名清晰filtered_value比f_val好得多能让人一眼看懂用途。初始化结构体有几种常见方式// 方式1声明时按顺序初始化C/C struct SensorData data1 {1630454400, 2048, 2047.5, 1, true}; // 方式2C99/C指定的初始化器更安全顺序无关 struct SensorData data2 { .sensor_id 2, .raw_value 4095, .timestamp 1630454500, .is_valid false, .filtered_value 0.0 }; // 方式3先声明后逐个赋值 struct SensorData data3; data3.timestamp 1630454600; data3.raw_value 1024; // ... 其他赋值实操心得在团队协作或维护旧代码时强烈推荐使用方式2指定初始化。即使未来结构体成员顺序发生变化或者新增了成员你的初始化代码也不会因此出错。这对于维护大型代码库稳定性非常有益。2.2 内存对齐看不见的性能与坑这是结构体进阶必须理解的概念。CPU访问内存时并不是以字节为单位而是以“字长”如4字节、8字节为单位。为了提升访问效率编译器会自动对结构体成员进行“内存对齐”。struct InefficientStruct { char a; // 1字节 int b; // 4字节 char c; // 1字节 short d; // 2字节 };你以为它的内存大小是 1412 8字节在32位系统默认4字节对齐上实际可能是12字节编译器会在char a后面插入3字节的“填充”让int b从4的倍数地址开始在char c后面插入1字节填充让short d从2的倍数地址开始。如何查看和优化可以使用sizeof运算符和offsetof宏。printf(Sizeof struct: %zu\n, sizeof(struct InefficientStruct)); printf(Offset of b: %zu\n, offsetof(struct InefficientStruct, b));优化技巧将大的、对齐要求严格的成员如double,int64_t放在前面小的、对齐要求宽松的如char,bool放在后面可以最大限度减少填充字节节省内存。这在嵌入式开发内存紧张或需要通过网络传输结构体数据时减少带宽占用尤其重要。struct EfficientStruct { int b; // 4字节 short d; // 2字节 char a; // 1字节 char c; // 1字节 // 编译器可能在此处添加2字节填充使整个结构体大小为4的倍数8字节 };这个优化后的版本大小很可能就是8字节。2.3 结构体数组与链表管理数据集合单个结构体用处有限我们通常需要管理一群结构体。结构体数组适用于元素数量固定、需要随机访问的场景#define MAX_STUDENTS 100 struct Student class[MAX_STUDENTS]; int student_count 0; // 添加一个学生如果数组未满 if (student_count MAX_STUDENTS) { class[student_count].age 20; strcpy(class[student_count].name, 王五); student_count; }结构体链表则适用于元素数量动态变化、频繁插入删除的场景。这也是搜索热词“c结构体链表基本语法”的核心。// 定义链表节点 struct ListNode { int data; struct ListNode* next; // 指向下一个节点的指针 }; // 创建链表、插入节点、遍历链表等操作需要配合动态内存管理malloc/free链表的核心在于每个节点结构体内部包含一个指向同类型节点的指针从而形成链式结构。它避免了数组大小固定的限制但失去了随机访问的能力访问第N个元素需要从头遍历。避坑指南处理链表时务必注意指针初始化和内存释放。新节点的next指针应初始化为NULL。在删除节点或释放整个链表时要确保不会出现“野指针”或“内存泄漏”。一个常见的技巧是使用“二级指针”或“返回新的头指针”来简化链表头节点的修改操作。3. 函数让结构体“活”起来结构体封装了数据而函数赋予了数据生命。函数操作结构体主要有三种方式传值、传指针、传引用C。3.1 传值 vs. 传指针效率与副作用的权衡传值调用函数收到的是结构体的一份完整拷贝。void printStudentByValue(struct Student stu) { printf(Name: %s\n, stu.name); // 修改stu只会影响函数内的副本不影响原数据 stu.age 100; }优点安全函数内部修改不会影响外部变量。 缺点当结构体很大时比如包含数个数组成员复制整个结构体的开销非常大影响性能。传指针调用函数收到的是结构体地址的拷贝。void printStudentByPointer(struct Student *pStu) { if (pStu NULL) return; // 良好的习惯检查指针有效性 printf(Name: %s\n, pStu-name); // 使用 - 操作符访问成员 pStu-age 100; // 这个修改会直接影响原结构体 } void calculateAverageScore(struct Student *array, int size, float *result) { float sum 0.0f; for(int i 0; i size; i) { sum array[i].score; // 通过指针访问数组元素 } *result sum / size; // 通过指针返回计算结果 }优点高效无论结构体多大只传递一个指针通常是4或8字节。函数可以直接修改原数据。 缺点存在意外修改原数据的风险需要程序员小心控制。选择策略只读操作如果函数只是读取结构体内容而不修改且结构体很小比如只有两三个基本类型成员传值简单安全。写入操作或结构体较大一律使用传指针。这是C语言中最常见的做法。对于“只读”的参数可以用const修饰指针增加安全性并表达意图。void printStudentConst(const struct Student *pStu) { // pStu-age 100; // 编译错误不能通过const指针修改数据 printf(Age: %d\n, pStu-age); }3.2 返回结构体从函数中“产出”数据函数也可以返回一个结构体。struct Student createStudent(const char* name, int age, float score) { struct Student s; strncpy(s.name, name, sizeof(s.name)-1); s.name[sizeof(s.name)-1] \0; // 确保字符串终止 s.age age; s.score score; return s; // 返回整个结构体 }在C语言中返回结构体意味着发生一次拷贝。现代编译器通常会进行“返回值优化”但为了代码清晰和效率更常见的模式是让调用者提供存储空间函数通过指针填充。// 更优的模式由调用者管理内存 bool createStudent(struct Student *s, const char* name, int age, float score) { if (s NULL) return false; // ... 填充s指向的结构体 ... return true; // 返回状态指示成功/失败 }这种模式在嵌入式或系统编程中非常普遍它明确了内存的所有权属于调用者避免了不必要的拷贝也便于错误处理。3.3 回调函数将行为作为参数传递这是函数指针与结构体结合的强大模式也是热词“回调函数c顿悟”所指的核心概念。它允许你将一个函数行为像数据一样传递给另一个函数。一个经典的应用场景是事件处理或遍历算法// 定义回调函数类型 typedef void (*DataProcessor)(struct SensorData*); // 一个可以处理数据数组的函数具体处理逻辑由回调函数决定 void processSensorDataArray(struct SensorData array[], int size, DataProcessor processor) { for (int i 0; i size; i) { if (array[i].is_valid) { processor(array[i]); // 调用回调函数处理当前数据 } } } // 具体的回调函数1打印数据 void printData(struct SensorData* data) { printf(Time: %u, Value: %.2f\n,>#include stdio.h #include string.h #include stdbool.h #define MAX_NAME_LEN 50 #define MAX_STUDENTS 100 // 1. 定义核心结构体 typedef struct { int id; // 学号 char name[MAX_NAME_LEN]; // 姓名 float score; // 成绩 } Student; // 2. 定义管理系统上下文结构体 typedef struct { Student students[MAX_STUDENTS]; // 学生数组 int count; // 当前学生数量 } StudentManager;这里我们做了两个关键设计使用typedef为结构体创建了别名Student和StudentManager这样后面就不需要每次都写struct关键字。StudentManager是一个“管理器”结构体它封装了学生数组和计数器使得状态管理更集中。这是一种简单的面向数据设计。4.2 核心功能函数的实现接下来我们实现针对StudentManager的增删改查函数。注意这些函数都接收StudentManager*指针以便直接修改管理器状态。// 3. 初始化管理器 void manager_init(StudentManager* mgr) { if (mgr NULL) return; mgr-count 0; memset(mgr-students, 0, sizeof(mgr-students)); // 清零数组 printf(学生管理系统已初始化。\n); } // 4. 添加学生 bool manager_add_student(StudentManager* mgr, int id, const char* name, float score) { if (mgr NULL || name NULL) return false; // 检查数组是否已满 if (mgr-count MAX_STUDENTS) { printf(错误学生数量已达上限(%d)\n, MAX_STUDENTS); return false; } // 检查学号是否重复简单的线性查找 for (int i 0; i mgr-count; i) { if (mgr-students[i].id id) { printf(错误学号 %d 已存在\n, id); return false; } } // 添加新学生 Student* new_stu mgr-students[mgr-count]; new_stu-id id; strncpy(new_stu-name, name, MAX_NAME_LEN - 1); new_stu-name[MAX_NAME_LEN - 1] \0; // 确保字符串安全终止 new_stu-score score; mgr-count; printf(成功添加学生%s (学号%d)\n, name, id); return true; } // 5. 根据学号查找学生返回指针便于后续修改 Student* manager_find_student_by_id(StudentManager* mgr, int id) { if (mgr NULL) return NULL; for (int i 0; i mgr-count; i) { if (mgr-students[i].id id) { return mgr-students[i]; // 返回找到的学生结构体的地址 } } return NULL; // 未找到 } // 6. 显示所有学生信息 void manager_display_all(const StudentManager* mgr) { if (mgr NULL) return; if (mgr-count 0) { printf(当前没有学生记录。\n); return; } printf(\n 所有学生信息 \n); printf(%-10s %-20s %-10s\n, 学号, 姓名, 成绩); printf(-----------------------------------\n); for (int i 0; i mgr-count; i) { printf(%-10d %-20s %-10.2f\n, mgr-students[i].id, mgr-students[i].name, mgr-students[i].score); } printf( 共 %d 名学生 \n\n, mgr-count); } // 7. 计算平均分演示如何通过指针返回结果 bool manager_calculate_average(const StudentManager* mgr, float* p_average) { if (mgr NULL || p_average NULL) return false; if (mgr-count 0) { *p_average 0.0f; return true; // 视为计算成功平均分为0 } float sum 0.0f; for (int i 0; i mgr-count; i) { sum mgr-students[i].score; } *p_average sum / mgr-count; return true; }4.3 主函数与用户交互最后我们编写一个简单的主函数来驱动这个系统形成一个可运行的完整程序。// 8. 主函数 int main() { StudentManager mgr; // 在栈上创建管理器实例 manager_init(mgr); // 初始化 // 添加一些测试数据 manager_add_student(mgr, 1001, 张三, 85.5f); manager_add_student(mgr, 1002, 李四, 92.0f); manager_add_student(mgr, 1003, 王五, 76.5f); // 显示所有学生 manager_display_all(mgr); // 查找并修改学生成绩 int search_id 1002; Student* found manager_find_student_by_id(mgr, search_id); if (found ! NULL) { printf(找到学生%s原成绩%.2f\n, found-name, found-score); found-score 95.0f; // 直接通过指针修改 printf(已将其成绩修改为%.2f\n, found-score); } else { printf(未找到学号为 %d 的学生。\n, search_id); } // 重新显示查看修改结果 manager_display_all(mgr); // 计算并显示平均分 float avg_score; if (manager_calculate_average(mgr, avg_score)) { printf(全班平均分%.2f\n, avg_score); } // 尝试添加重复学号应失败 manager_add_student(mgr, 1001, 赵六, 88.0f); return 0; }编译与运行 将以上所有代码块按顺序保存到一个文件如student_system.c使用C编译器编译运行。gcc -o student_system student_system.c -Wall ./student_system系统输出示例学生管理系统已初始化。 成功添加学生张三 (学号1001) 成功添加学生李四 (学号1002) 成功添加学生王五 (学号1003) 所有学生信息 学号 姓名 成绩 ----------------------------------- 1001 张三 85.50 1002 李四 92.00 1003 王五 76.50 共 3 名学生 找到学生李四原成绩92.00 已将其成绩修改为95.00 所有学生信息 学号 姓名 成绩 ----------------------------------- 1001 张三 85.50 1002 李四 95.00 1003 王五 76.50 共 3 名学生 全班平均分85.67 错误学号 1001 已存在4.4 从示例中学到的关键点数据与操作的绑定StudentManager结构体将数据学生数组和状态数量封装在一起所有操作函数都围绕它展开代码组织清晰。指针的灵活运用manager_find_student_by_id返回一个指针这使得查找后的修改操作非常高效和直接无需再次查找或拷贝数据。错误处理函数通过返回bool类型或检查NULL指针来指示操作成功与否这是健壮性编程的基本要求。模块化思想每个函数职责单一。manager_display_all只负责显示manager_calculate_average只负责计算。这使得代码易于测试、理解和维护。可扩展性这个简单的框架可以轻松扩展。例如你可以很容易地添加按成绩排序、将数据保存到文件、从文件加载数据等功能只需增加新的函数而无需大幅改动现有结构。这个实战项目虽然小但它完整地展示了结构体与函数如何协同工作构建出一个功能清晰、逻辑完整的小型系统。理解了这套模式你就能应对更复杂的、由成百上千个结构体和函数组成的大型项目。

相关新闻

批量更新主键排序防死锁 标准化规范(错误案例+正确案例+原理复盘)

批量更新主键排序防死锁 标准化规范(错误案例+正确案例+原理复盘)

批量更新主键排序防死锁 标准化规范(错误案例正确案例原理复盘) 一、核心概述 数据库批量更新、批量删除场景下,90%偶发性死锁、无规律锁超时故障,均源于「多线程事务加锁顺序不一致」。该类问题本地单线程测试100%正常&#xf…

2026/8/17 0:23:41 阅读更多 →
二叉树_堆的实现

二叉树_堆的实现

1.树树是一种非线性的数据结构,是由m(m>0)个有限节点组成的有层次关系的结合,树的结构中,子树之间是不能有交集的否则就是图,树是递归定义的。常见树的相关术语:⽗结点:若⼀个结点含有⼦结点&#xff0c…

2026/8/15 22:39:28 阅读更多 →
审计专业考研和考证怎么规划

审计专业考研和考证怎么规划

考研和考证,是审计专业学生绕不开的成长主题。很多人在大二大三就开始纠结:应该先全力准备考研,还是趁在校多拿几个证书?其实两者并非对立,如果能结合职业方向做一份清晰的规划,反而能相互借力。这篇文章梳…

2026/8/15 22:38:28 阅读更多 →

最新新闻

从零构建轻量级前端埋点SDK:TypeScript与Rollup实战指南

从零构建轻量级前端埋点SDK:TypeScript与Rollup实战指南

1. 项目缘起:为什么我们要自己造一个埋点SDK的轮子? 在任何一个有一定规模的Web应用中,数据都是驱动产品迭代和业务决策的燃料。用户点击了哪个按钮?页面停留了多久?某个新功能的使用率如何?这些问题的答案…

2026/8/18 6:41:14 阅读更多 →
Dorado7企业级前端快速开发平台:核心概念、环境搭建与调试实战

Dorado7企业级前端快速开发平台:核心概念、环境搭建与调试实战

1. 项目概述:为什么今天还要聊Dorado7?最近在整理一些遗留的老项目,又翻出了Dorado7的代码。说实话,现在前端框架日新月异,Vue、React、Angular三足鼎立,再回头去看这个基于jQuery时代的“企业级前端展现中…

2026/8/18 6:41:14 阅读更多 →
HAT-4D:人机协作从单目视频重建动态交互4D场景

HAT-4D:人机协作从单目视频重建动态交互4D场景

1. 项目概述:从单目视频到动态交互世界的重建最近在计算机视觉和三维重建领域,一个名为“HAT-4D”的项目引起了我的注意。这个标题初看有点唬人,但拆解开来其实非常有意思:HAT-4D: Lifting Monocular Video for 4D Multi-Object I…

2026/8/18 6:41:14 阅读更多 →
MOS管发热问题全解析:从损耗原理到选型、驱动与PCB布局优化

MOS管发热问题全解析:从损耗原理到选型、驱动与PCB布局优化

1. 从“炸管子”的恐惧说起:MOS管发热的本质最近在调试一块新的电机驱动板,又闻到了那股熟悉的、带着一丝焦糊味的“电子香气”。没错,一个MOS管又因为过热而英勇就义了,外壳鼓起,甚至炸裂,留下一片狼藉。这…

2026/8/18 6:41:14 阅读更多 →
多智能体强化学习在延迟反馈场景下的三方调度与目标权重自适应实践

多智能体强化学习在延迟反馈场景下的三方调度与目标权重自适应实践

1. 项目概述:从延迟市场反馈中学习,实现三方调度的目标权重自适应最近在折腾一个挺有意思的项目,核心是解决一个在真实商业场景里普遍存在,但学术界讨论相对较少的问题:如何在多智能体强化学习的框架下,处理…

2026/8/18 6:40:14 阅读更多 →
从高镍811到中镍高压:动力电池技术演进与市场选择的深度解析

从高镍811到中镍高压:动力电池技术演进与市场选择的深度解析

1. 从一则旧闻说起:为什么我们今天还要聊“高镍811”?前几天翻看行业旧资料,又看到了2019年那则新闻:“江铃新能源销量大增65%,国轩高科2019年试产高镍811软包电池”。当时这消息在圈内激起过不小的水花,但…

2026/8/18 6:40:14 阅读更多 →

日新闻

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 如果你还停留在"看网课 不停暂停 截图 …

2026/8/18 0:00:57 阅读更多 →
思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 你是不是也经历过这种时刻:设计稿里…

2026/8/18 0:00:58 阅读更多 →
华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, …

2026/8/18 0:00:59 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/17 2:58:27 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/17 2:58:30 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/17 2:58:32 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/17 18:54:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/17 18:55:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/17 18:55:55 阅读更多 →