当前位置: 首页 > news >正文

15_结构体联合与枚举_组织复杂数据

结构体、联合与枚举组织复杂数据一、本篇文章要解决什么问题前面你学过的数据类型都是单个的一个 int、一个 double、一个 char。但现实中很多数据是打包在一起的——比如一个学生的信息包括学号int、姓名char 数组、成绩double你不能用三个独立的变量随便放着因为张三的学号和李四的成绩之间没有关联。这篇文章帮你搞定三件事struct 怎么把不同类型的数据打包成一个整体怎么通过.和-访问结构体成员union 和 enum 分别在什么场景下用二、先用一个简单例子理解2.1 档案袋的故事你去学校教务处每个学生有一个档案袋袋子上写着名字里面装着学号条、成绩单、体检表。不同的材料类型不同数字、文字、表格但都装在一个袋子里形成一个整体。这个档案袋就是结构体struct——把不同类型的数据打包在一起起一个名字当作一个整体来传递。2.2 union 就是一物多用的格子一个储物柜的格子今天放书包明天放篮球。同一块空间不同时间可以存不同类型的东西——这就是联合union。2.3 enum 就是给数字起个好记的名字红灯0、绿灯1、黄灯2——这就是枚举enum。用RED比用0更可读。三、核心知识点讲解3.1 struct 的定义和使用#includestdio.h#includestring.hstructStudent{intid;// 学号charname[20];// 姓名doublescore;// 成绩};intmain(void){structStudentstu1;// 定义一个结构体变量stu1.id1001;strcpy(stu1.name,Zhang);stu1.score95.5;printf(学号%d\n,stu1.id);printf(姓名%s\n,stu1.name);printf(成绩%.1f\n,stu1.score);return0;}运行结果学号1001 姓名Zhang 成绩95.5定义时直接初始化structStudentstu2{1002,Li,88.0};图15-1 结构体内存布局图帮助理解结构体成员在内存中的排列。3.2 结构体数组——一个班的学生structStudentclass[3]{{1001,Zhang,95.5},{1002,Li,88.0},{1003,Wang,76.5}};for(inti0;i3;i){printf(%d %s %.1f\n,class[i].id,class[i].name,class[i].score);}图15-2 结构体数组示意图帮读者理解结构体数组的连续存储。3.3 结构体指针——用 - 访问成员structStudentstu{1001,Tom,90.0};structStudent*pstu;// 两种访问方式等价printf(%d\n,(*p).id);// 先解引用再取成员——括号必须有printf(%d\n,p-id);// 箭头运算符——更简洁.和-的区别.用于结构体变量-用于结构体指针。p-member等价于(*p).member。初学者常把这两个搞混——看到指针就用-看到变量就用.。图15-3 . 和 - 运算符的使用场景图让初学者记住变量用点、指针用箭头。3.4 联合 union——同一块空间的不同解读#includestdio.hunionData{inti;doubled;charc;};intmain(void){unionData u;u.i65;printf(u.i %d (占用 %u 字节)\n,u.i,(unsignedint)sizeof(u.i));u.cA;printf(u.c %c\n,u.c);// 注意此时 u.i 的值已经被覆盖了——因为 i 和 c 共用同一块空间printf(整个 union 大小%u 字节\n,(unsignedint)sizeof(u));// sizeof(union Data) 等于最大成员的大小return0;}union 所有成员共享同一块内存空间union 的大小等于其最大成员的大小。同一时间只能使用一个成员——你写入一个成员其他成员的值就被覆盖了。图15-4 union 和 struct 内存占用对比图一目了然地展示 union 的 “共享空间” 特性。3.5 枚举 enum——给整数起别名#includestdio.henumColor{RED,GREEN,BLUE};// RED0, GREEN1, BLUE2enumStatus{OK200,NOT_FOUND404,ERROR500};intmain(void){enumColorcRED;printf(RED %d\n,c);// 输出 0enumStatussNOT_FOUND;printf(NOT_FOUND %d\n,s);// 输出 404return0;}如果不手动指定值枚举从 0 开始递增。也可以手动赋任意值。四、完整代码示例一个学生信息管理的基础版本用结构体数组存储数据用函数指针选择操作#define_CRT_SECURE_NO_WARNINGS#includestdio.h#includestring.h#defineMAX_STUDENTS50#defineNAME_LEN30structStudent{intid;charname[NAME_LEN];doublescore;};// 打印单个学生voidprintStudent(conststructStudent*s){printf(学号%d 姓名%-10s 成绩%.1f\n,s-id,s-name,s-score);}// 打印所有学生voidprintAll(conststructStudentarr[],intcount){printf(\n 学生列表共 %d 人\n,count);for(inti0;icount;i){printf([%d] ,i1);printStudent(arr[i]);}}intmain(void){structStudentstudents[MAX_STUDENTS]{{1001,Zhang,95.5},{1002,Li,88.0},{1003,Wang,76.5}};intcount3;intchoice;do{printf(\n1. 显示所有学生\n);printf(2. 添加学生\n);printf(0. 退出\n);printf(请选择);scanf(%d,choice);switch(choice){case1:printAll(students,count);break;case2:if(countMAX_STUDENTS){printf(学生已满\n);break;}printf(请输入学号、姓名、成绩);scanf(%d %19s %lf,students[count].id,students[count].name,students[count].score);count;printf(添加成功\n);// 注意%s 遇到空格就停所以姓名不能含空格。// 如需支持Zhang San这类姓名应改用 fgets 读取整行break;case0:printf(再见\n);break;default:printf(无效选择\n);}}while(choice!0);return0;}五、运行结果1. 显示所有学生 2. 添加学生 0. 退出 请选择1 学生列表共 3 人 [1] 学号1001 姓名Zhang 成绩95.5 [2] 学号1002 姓名Li 成绩88.0 [3] 学号1003 姓名Wang 成绩76.5 1. 显示所有学生 2. 添加学生 0. 退出 请选择2 请输入学号、姓名、成绩1004 Zhao 82.0 添加成功 1. 显示所有学生 2. 添加学生 0. 退出 请选择0 再见六、代码逐行解析结构体作为函数参数——传指针而非传值voidprintStudent(conststructStudent*s)为什么不直接传struct Student s因为结构体可能很大如果有很多字段值传递会完整复制一份——既慢又浪费内存。传指针只复制 4 或 8 字节的地址。const保证函数不会修改原始数据。结构体数组成员访问students[count].idstudents[count]是数组中的一个结构体变量.id访问它的成员。如果要写成指针形式(students count)-id。do while 菜单循环do{...}while(choice!0);菜单至少显示一次用户选 0 才退出——这是典型的 do while 场景。七、初学者常见错误错误1忘记 struct 关键字C 中不能省略// C 语言中structStudentstu;// 正确Student stu;// 错误除非用了 typedef见第 16 篇错误2结构体指针用 . 而不是 -structStudent*pstu;p.name// 错误p 是指针用 - 或 (*p).namep-name// 正确错误3用 比较两个结构体structStudents1{...},s2{...};if(s1s2){...}// 编译错误结构体不能直接用 比较// 需要逐个成员比较错误4union 同时使用多个成员unionData u;u.i65;u.cA;// u.i 的值现在无效了不要同时依赖两个成员错误5enum 的值被当成字符串enumColor{RED,GREEN};printf(%s\n,RED);// 错误输出的是整数 0不是 RED// 需要手动维护名称数组来转换八、练习题练习题1分数统计定义结构体struct Score { double chinese; double math; double english; }。用户输入 3 科成绩程序计算总分和平均分存入结构体并输出。练习题2按成绩排序在完整代码示例的学生数组中按成绩从高到低排序并输出。用冒泡排序交换整体结构体结构体可以直接赋值struct Student temp arr[i]; arr[i] arr[j]; arr[j] temp;。练习题3用 enum 表示星期定义一个enum Weekday { MON1, TUE, WED, THU, FRI, SAT, SUN }。用户输入 1~7 的数字程序输出对应的星期名称。九、本篇总结struct 把不同类型数据打包作为一个整体使用。访问成员用.变量或-指针结构体数组适合批量管理相同结构的数据如一个班的学生union 成员共享同一块内存大小等于最大成员同时只能用其中一个enum 给整数常量起好记的名字提高代码可读性函数传结构体建议用指针避免大量数据复制
http://www.rkmt.cn/news/1374077.html

相关文章:

  • 一小时搭建爬虫数据提取智能体 · 数据矿工
  • 多层感知机
  • 2026年紫外线杀菌除藻灯优质厂家深度解析:聚焦技术、产能与服务三角 - 2026年企业推荐榜
  • ubuntu2026.04部署k8s1.36版本的傻瓜式教程(注:运行时为docker,网络插件为calico)
  • DFT笔记59
  • 高通骁龙处理器深度解码:从移动通信霸主到全场景智能计算引擎
  • 告别SSH断连焦虑:手把手教你用Screen在Linux后台挂起任务(含源码编译避坑)
  • Win7专业版电脑重启后时间服务总停止?三步设置让它稳定运行(附命令详解)
  • 鸿蒙数理体系创作说明 (鸿蒙数学一阶完结后更新说明)
  • 在CentOS7服务器上装Win10?手把手教你用Ventoy搞定双系统(附网卡驱动安装避坑指南)
  • 2026年知名的大豆定量包装机/饲料定量包装机厂家哪家好 - 行业平台推荐
  • 2026靠谱仪器推荐:Trim200离子束刻蚀机、Essent Optics分光光度计、LINZA分光光度计、LensCheck MTF传函仪选择指南 - 优质品牌商家
  • Vibing Steampunk,一座把 Claude Code、MCP 和 SAP ADT 接到一起的 ABAP 工程桥
  • 2026北京搬家公司优质推荐指南:北京公司搬家公司/北京收纳整理公司/北京日式搬家公司/北京本地搬家/北京企业搬家/选择指南 - 优质品牌商家
  • Codex入门17-上下文管理(高手秘技:如何让AI精准理解你的百万行大型项目)
  • Zynq的QSPI Flash替换为GD25Q32故障排查
  • 问题分析-并网逆变器炸机问题
  • 别再死记硬背了!用Python代码一次性搞懂曼哈顿、欧式、切比雪夫距离的底层联系
  • 2026免费在线去水印软件推荐,手把手教你5种方法,第三种0.3秒搞定!
  • 2026保姆级免费去图片水印App教程,一键无痕去除,这4款微信小程序最省心
  • 2026最好用的图片处理工具推荐:去水印 / 抠图 / 高清化实测对比
  • Claude Code 接入 DeepSeek
  • 2026专业音响设备应用白皮书文体场馆选型剖析:ZOBO音响、舞台音响、Montarbo音响、Nettuno音响选择指南 - 优质品牌商家
  • 焊接钢格板哪个好?厂家怎么选?实用推荐来啦!
  • 保姆级教程!零代码搞定学生考勤高危群体画像分析(指标卡 + 饼图 + 仪表盘,附完整操作步骤)
  • 告别.bash_profile:在macOS Ventura/Sonoma上为Maven配置环境变量的几种新方法(含Zsh教程)
  • Win10桌面右键新建菜单丢了记事本?别慌,手把手教你用注册表找回来(附权限设置详解)
  • C51开发中寄存器变量限制与优化策略
  • VMware虚拟机里装FydeOS,给旧电脑或MacBook找个轻量‘副系统’
  • AR项目想拿高分?试试用Vuforia虚拟按钮做交互:从选图到避坑全流程