C语言如何在main函数中调用带结构体数组与浮点数组参数的GetAverage函数
现有函数设计的核心问题
- 你当前写的函数声明
float GetAverage(struct Info fStudent[studVar+1], float funcVar[gradeVar+1])没法通过编译:形参位置引用的studVar、gradeVar是main函数的局部变量,在函数定义阶段根本没有可见性,而且C语言规定函数形参里的数组长度标记会被编译器直接忽略,写不写完全不影响实际传参的是数组首地址。 - 这个设计本身逻辑就有漏洞:函数拿不到你要计算的是哪名学生的成绩,传整个结构体数组、整个成绩数组进去,根本定位不到当前要计算的成绩块,就算编译过了也没法算出正确值。
修正后的GetAverage实现
这个函数的核心目标是计算单名学生的课程平均分,不需要传入整个学生结构体数组——计算平均分只需要拿到该学生的成绩块首地址、对应的课程门数就够了,完全没必要绑定结构体数组参数。
正确的函数参考实现:
/** * 计算单名学生的课程平均分 * @param curStuGrades 当前学生的成绩数组首地址 * @param courseCount 当前学生修的课程总数(已经过校验,取值1-10) * @return 计算得到的平均分 */ float GetAverage(float *curStuGrades, int courseCount) { float scoreTotal = 0.0f; for (int i = 0; i < courseCount; i++) { scoreTotal += curStuGrades[i]; } return scoreTotal / courseCount; }
main函数中的正确调用流程
你已经在main里完成了所有合法性校验,且定义了学生结构体数组Student、全局成绩数组studGrades,只要按照你的成绩存储规则定位到每名学生的成绩块,循环调用函数即可:
- 如果你的成绩数组是按“第i名学生的连续gradeVar门成绩存在数组的连续位置”存储的(这也是绝大多数同类程序的存储方式),直接按块取地址调用:
for (int stuIndex = 0; stuIndex < studVar; stuIndex++) { // 定位到当前学生的成绩块起始地址 float *currentBlock = &studGrades[stuIndex * gradeVar]; // 调用函数计算平均分,存到对应学生的结构体成员里(记得提前在struct Info里加float average字段存结果) Student[stuIndex].avgScore = GetAverage(currentBlock, gradeVar); }
- 如果你坚持要按最初的设计传入结构体数组和成绩数组,那必须额外给函数传当前计算的学生下标作为参数,不然函数根本不知道要读哪段成绩:
修正后的函数定义为:
对应的main中调用代码为:float GetAverage(struct Info allStu[], float allGrades[], int targetStuIdx, int courseCount) { float *curGrades = &allGrades[targetStuIdx * courseCount]; float total = 0.0f; for(int i = 0; i < courseCount; i++) { total += curGrades[i]; } return total / courseCount; }for (int stuIndex = 0; stuIndex < studVar; stuIndex++) { Student[stuIndex].avgScore = GetAverage(Student, studGrades, stuIndex, gradeVar); }
容易踩的逻辑坑
- 累加总分数的时候一定要初始化为
0.0f,不能让变量留栈上的随机初始值,不然计算结果会出现随机的大数 - 因为你已经做了课程数的范围校验,不存在
courseCount为0的除零问题,不需要额外加容错判断 - 不要在循环累加过程中提前做除法,必须等所有成绩累加完成后再除以课程数,不然会出现累计误差
内容的提问来源于stack exchange,提问作者daniel flores
相关产品推荐
相关产品推荐

