是否有结构属性的占位符? (C)

Are there placeholders for attributes of a struct? (C)

我正在尝试 CS50 的滤镜,但我正在处理像素模糊部分。我可以使用

访问像素的颜色
image[row][pixel].rgbtRed
image[row][pixel].rgbtGreen
image[row][pixel].rgbtBlue

我希望能够调用一个函数来计算周围像素的平均值并传入我想要的平均值的颜色。是否有某种占位符,以便我可以访问结构的特定 element/attribute? (不确定它的正确名称抱歉)。

我还是个新手,试过把它放在括号之间等等,但没有任何效果。

这是我尝试获取传递颜色值的函数。

float calcAverage(int height, int width, RGBTRIPLE image[height][width], int row, int pixel, string color)
{
    float sum =  image[row][pixel].color + image[row][pixel - 1].color; 
    return 0;
}

这就是我调用函数的方式。

redAverage = calcAverage(height, width, image, row, pixel, "rgbtRed");

现在我的 .color 计划不起作用,因为知道他正在寻找一个名为 color 的属性。这是我得到的错误

error: no member named 'color' in 'RGBTRIPLE'
float sum =  image[row][pixel].color + image[row][pixel - 1].color;

出于测试目的,我保留了简短的总和。在此先感谢,我开始认为这是不可能的,我应该离开它。再次抱歉,如果我用错了我正在寻找的术语。

您不能使用字符串变量代替成员名称。您需要检查字符串的值和 select 基于该值的字段。

float calcAverage(int height, int width, RGBTRIPLE image[height][width], 
                  int row, int pixel, string color)
{
    if (!strcmp(color, "rgbtRed")) {
        return image[row][pixel].rgbtRed + image[row][pixel - 1].rgbtRed;
    } else if (!strcmp(color, "rgbtGreen")) {
        return image[row][pixel].rgbtGreen + image[row][pixel - 1].rgbtGreen;
    } else if (!strcmp(color, "rgbtBlue")) {
        return image[row][pixel].rgbtBlue + image[row][pixel - 1].rgbtBlue;
    } else {
        // invalid color
        return 0;
    }
}

这可以通过成员的偏移来完成,如下面的代码所示。从某种意义上说,使用它有点笨拙。但是,它在某些情况下可能有用且合适。因为使用了显式转换,覆盖了关于类型的常见编译器警告,所以必须小心。

typedef struct { float red, green, blue; } RGBTRIPLE;


#include <stdio.h>
#include <stddef.h>


/*  Get the offset of a member in an RGBTRIPLE using the C standard "offsetof"
    feature.  This could be a function, preferably a static inline function
    visible where it is used.
*/
#define OffsetOf(member)    (offsetof(RGBTRIPLE, member))

/*  Get a member of an RGBTRIPLE by its offset.

    This uses the offset to locate the member and then converts the address to
    a pointer to the member type, which we then use with "*" to refer to the
    member.  That produces an lvalue for the member which can be used to read
    (use the value of) or write (assign to) the member.

    This must be a macro because a function cannot return an lvalue.
*/
#define MemberByOffset(Structure, Offset) \
    (*(float *)((char *) &Structure + Offset))


static float Average(RGBTRIPLE *Array, size_t Offset)
{
    static const size_t N = 2;  // For demonstration only.

    float sum = 0;
    for (size_t i = 0; i < N; ++i)
        sum += MemberByOffset(Array[i], Offset);

    return sum/N;
}


int main(void)
{
    RGBTRIPLE Array[] = {{ 10, 20, 30 }, { 100, 200, 300 }};
    printf("Red average = %g.\n",   Average(Array, OffsetOf(red  )));
    printf("Green average = %g.\n", Average(Array, OffsetOf(green)));
    printf("Blue average = %g.\n",  Average(Array, OffsetOf(blue )));
}