简体   繁体   English

将结构成员作为参数传递给 C 中的 Function

[英]Passing Struct Members as Parameter to a Function in C

Say I have the following code for taking the average of the class' math and science grade.假设我有以下代码来获取班级数学和科学成绩的平均值。

typedef struct
{
    char name[30];
    float math;
    float science;
}
grade;
int n = 5;
grade grades[n];

float math_average(int n)
{
    float run_sum = 0;
    for (int i = 0; i < n; i++)
    {
        run_sum += grades[i].math;
    }
    return (run_sum / n);
}

float science_average(int n)
{
    float run_sum = 0;
    for (int i = 0; i < n; i++)
    {
        run_sum += grades[i].science;
    }
    return (run_sum / n);
}

Is it possible to create a generalized average function to have the same effect?是否可以创建一个广义平均function 以产生相同的效果? So instead of n of subjects functions, I only have 1. Something like passing the subject as a parameter perhaps?因此,我只有 1 个主题函数,而不是n 个主题函数。也许像将主题作为参数传递之类的东西? Included example to better visualize of what I want to achieve:包含的示例可以更好地可视化我想要实现的目标:

float average(int n, /* [SUBJECT] */)
{
    float run_sum = 0;
    for (int i = 0; i < n; i++)
    {
        run_sum += grades[i]./*SUBJECT*/;
    }
    return (run_sum / n);  
}

In general, if you have N variables (fields) of the same nature, you don't have N declarations, you declare an array of N elements.一般来说,如果你有N个相同性质的变量(字段),你没有N个声明,你声明一个包含N个元素的数组。 Hence因此

#define MATH 0
#define SCIENCE 1
#define NUM_SUBJECTS 2

typedef struct
{
    char name[30];
    float subjects[NUM_SUBJECTS];
} grade;

Instead of writing grades[i].math you write grades[i].subjects[MATH] .而不是写grades[i].math你写grades[i].subjects[MATH] And of course now you can write a general average routine by referring to grades[i].subjects[j] .当然,现在您可以通过参考grades[i].subjects[j]来编写一般平均例程。

Now if you would've thought that this sequence of #define s at the beginning is dangerously stupid, you'd be right.现在,如果您认为开头的#define序列非常愚蠢,那么您是对的。 I've only put them there for illustration.我把它们放在那里只是为了说明。 In reality, you use a single enum declaration instead:实际上,您使用单个enum声明来代替:

enum subjects { MATH, SCIENCE, NUM_SUBJECTS };

You just need to keep NUM_SUBJECTS the last item in the list when you extend your list of subjects.当您扩展主题列表时,您只需将NUM_SUBJECTS保留在列表中的最后一项。

This approach naturally extends to the case when your list of subjects is not set in stone, but instead is one of the inputs of your program.当您的主题列表不是一成不变的,而是您的程序的输入之一时,这种方法自然会扩展到这种情况。 You will need a dynamic array in one guise or another, for instance例如,您将需要一种或另一种形式的动态数组

typedef struct
{
    char name[30];
    int num_subjects;
    float *subjects;
} grade;

but the generic average function code will remain unchanged .但通用平均 function 代码将保持不变

If you want, you can use offsetof .如果需要,可以使用offsetof

float average(int n, int offset)
{
    float run_sum = 0;
    for (int i = 0; i < n; i++)
    {
        //it's a little ugly, but should work as long as your average fields are float
        run_sum += *(float*)(((byte*)&grades[i]) + offset);
    }
    return (run_sum / n);
}

math_average => average(n, offsetof(grade, math)) and so on... math_average => average(n, offsetof(grade, math))等等...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM