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

别再死记结构体了:用一个真实的学生成绩统计程序,彻底搞懂结构体数组和指针

摘要

这一章的核心是结构体数组 + 结构体指针 + 函数化设计
为了不让“结构体”只停留在书本例子里,我们把教材中的学生成绩结构体,改造成一个“班级成绩统计与优秀学生筛选小工具”

这个小程序模拟的是:
老师或班长在期末录入学生成绩,程序自动算出每个学生的平均分,并找出平均成绩最高的学生,把他的完整信息输出出来。

通过这个例子,可以非常直观地理解:

  • 为什么要用结构体数组
  • 为什么函数之间要传结构体指针
  • 函数返回结构体到底有什么用

描述(实际使用场景)

假设你是班长,老师让你帮忙做一件事:

“把 3 个学生的学号、姓名、三门课成绩录入电脑,
自动算平均分,
然后把成绩最好的那个学生信息单独打印出来。”

如果不用结构体,你可能要用一堆数组:

  • 一个数组存学号
  • 一个数组存姓名
  • 三个数组存三门课成绩
  • 再来一个数组存平均分

这种写法不仅乱,而且非常容易出错。

结构体的作用,就是把“一个学生”当成一个整体来处理。
再配合结构体数组,就可以一次性管理多个学生。

题解答案(整体思路)

整个程序严格按照教材要求拆成 3 个函数,每个函数只干一件事:

input 函数

  • 输入每个学生的信息
  • 计算每个学生的平均成绩

max 函数

  • 在所有学生中,找出平均成绩最高的那一个
  • 返回这个学生的结构体

print 函数

  • 把“成绩最高的学生”的完整信息输出出来

主函数只负责:

  • 定义结构体数组
  • 用结构体指针调用这三个函数
  • 不直接参与具体逻辑

题解代码分析(完整代码 + 逐段解释)

结构体定义

#include<stdio.h>#defineN3// 学生人数structStudent{intnum;// 学号charname[20];// 姓名floatscore[3];// 三门课程成绩floataver;// 平均成绩};

这一部分在干什么?

  • struct Student描述的是一个学生
  • score[3]表示三门课成绩
  • aver是后面计算出来的结果

这样一来,一个结构体变量,就完整地表示了一个学生。

主函数:只负责“调度”

intmain(){voidinput(structStudentstu[]);structStudentmax(structStudentstu[]);voidprint(structStudentstud);structStudentstu[N];structStudent*p=stu;// 结构体指针指向数组首地址input(p);// 输入数据并计算平均分print(max(p));// 找最高分学生并输出return0;}

这里是本题的关键设计点

  • stu是结构体数组,存 3 个学生
  • p是指向结构体的指针

为什么要用指针?

因为:

  • 数组名本身就是地址
  • 用指针传参效率高
  • 这是后面动态管理数据的基础写法

input 函数:输入数据 + 算平均分

voidinput(structStudentstu[]){inti,j;floatsum;printf("请输入各学生的信息:学号 姓名 三门课成绩\n");for(i=0;i<N;i++){printf("第%d个学生:\n",i+1);scanf("%d %s",&stu[i].num,stu[i].name);sum=0;for(j=0;j<3;j++){scanf("%f",&stu[i].score[j]);sum+=stu[i].score[j];}stu[i].aver=sum/3;}}

这一段的实际意义

你可以把它理解成:

“把 Excel 表里的学生数据,一行一行输进程序里。”

  • 每输入一个学生
  • 同时把平均分算好存起来
  • 后面的函数直接用结果,不重复计算

这是非常典型的“一次计算,多次使用”的思想。

max 函数:找平均分最高的学生

structStudentmax(structStudentstu[]){inti;intmaxIndex=0;for(i=1;i<N;i++){if(stu[i].aver>stu[maxIndex].aver){maxIndex=i;}}returnstu[maxIndex];}

这里为什么返回结构体?

因为我们需要的不是:

  • 最高分是多少

而是:

  • 这个学生是谁
  • 他的学号、姓名、成绩、平均分都要

所以最干净的方式,就是直接返回整个结构体

这也是很多同学第一次真正理解:

原来函数是可以返回结构体的。

print 函数:输出最终结果

voidprint(structStudentstud){inti;printf("\n平均成绩最高的学生信息:\n");printf("学号:%d\n",stud.num);printf("姓名:%s\n",stud.name);printf("成绩:");for(i=0;i<3;i++){printf("%.2f ",stud.score[i]);}printf("\n平均成绩:%.2f\n",stud.aver);}

这个函数的好处

  • 专门负责输出
  • 不关心数据怎么来的
  • 不关心怎么算的

以后你想把输出改成:

  • 文件输出
  • 图形界面
  • 网络上传

只需要改这个函数。

示例测试及结果

输入示例

请输入各学生的信息:学号 姓名 三门课成绩 第1个学生: 1001 张三 85 90 88 第2个学生: 1002 李四 78 80 82 第3个学生: 1003 王五 92 95 93

输出结果

平均成绩最高的学生信息: 学号:1003 姓名:王五 成绩:92.00 95.00 93.00 平均成绩:93.33

这正是我们一开始设定的使用目标。

时间复杂度

  • 输入函数:遍历 N 个学生,时间复杂度 O(N)
  • 查找最大平均分:再遍历一次,时间复杂度 O(N)

整体时间复杂度是:

O(N)

对于学生数量增加,性能是线性增长,非常合理。

空间复杂度

  • 使用了一个结构体数组stu[N]
  • 额外变量都是常数级

空间复杂度为:

O(N)

总结

这个例子虽然是教材题,但它已经非常接近真实开发中的数据处理逻辑:

  • 用结构体描述现实对象
  • 用结构体数组管理一组对象
  • 用指针在函数间高效传递数据
  • 用函数拆分逻辑,主函数保持干净

如果你把这个例子真正吃透了:

  • 后面学文件读写
  • 动态内存
  • 链表
  • 简单管理系统

都会非常顺。

http://www.jsqmd.com/news/89556/

相关文章:

  • Turnitin系统查英文AI率多少为正常?报告显示星号*%怎么办?
  • 新生入学必备!这几款APP帮你开启开挂大学生活 - 品牌测评鉴赏家
  • 浏览器原理
  • 利用 vn.py 实现波动率倒数仓位:把螺纹钢回测年化从 9% 提到 89% 的完整笔记
  • 简单使用FalkorDB和Neo4j图数据库
  • Docker学习笔记—day012
  • 基于组合赋权法(BWM+CRITIC)与可拓云理论的综合风险评估模型MATLAB代码
  • 微信小程序开发实战之 04-微信小程序常用 API(上)
  • Netty Http协议
  • Chasys Draw IES Artist:开源免费的图像处理与图形设计全能工具
  • 1.20 深度学习优化器对比
  • 什么是 Backtrader?一篇给 Python 量化爱好者的超全说明书
  • 多签钱包:多人签名才能执行的操作
  • 我在学c语言分支和循环的见解和踩过的坑
  • CANFD 总线多节点扩展技术:节点数量限制与突破方案
  • 今天我们继续学习kubernetes内容Helm
  • REAPER数字音频工作站:轻量高效的专业音频制作解决方案
  • 配电网可靠性评估—序贯蒙特卡洛模拟法研究附Matlab代码
  • 托福培训机构深度测评:从师资到服务,哪家用数据征服了90%的考生? - 品牌测评鉴赏家
  • 光伏储能虚拟同步发电机Simulink仿真模型探究
  • 机器学习资源合集
  • linux中的一些配置
  • 数据结构==B-树==
  • OBS Studio:开源免费的屏幕录制与直播推流一体化解决方案
  • Python GIL 的前世今生
  • 数字电路模拟程序复盘分析
  • ansible事实详解
  • COMSOL助力煤层注气热力流THM耦合下增强甲烷开采探索
  • Nlp教程资源合集
  • .NET 10 网络堆栈深度架构解析:HTTP/3、性能优化与后量子加密的融合演进