如何实现对结构的各个字段执行相同操作的函数?

时间:2014-10-21 16:40:27

标签: c oop struct

我有以下结构:

struct tmatrix {
    struct tmatrix_entry {
        double price;
        double amt;
    } **entries;

    double *stocks;
    double *needs;
    int rows;
    int cols;
};

以及以下功能:

void tmatrix_set_prices (struct tmatrix *tm, double *prices[]) {
    for (int i = 0; i < tm->rows; ++i)
        for (int j = 0; j < tm->cols; ++j)
            tm->entries[i][j].price = (prices) ? prices[i][j] : 0;
}

void tmatrix_set_amts (struct tmatrix *tm, double *amts[]) {
    for (int i = 0; i < tm->rows; ++i)
        for (int j = 0; j < tm->cols; ++j)
            tm->entries[i][j].amt = (amts) ? amts[i][j] : 0;
}

我认为制作2个几乎相同的功能并不酷,所以到目前为止我已经达到了这个目的:

#define TMATRIX_SET_2D_ARRAY(TM, FIELD, ARRAY)\
do {\
    for (int i = 0; i < TM->rows; ++i)\
        for (int j = 0; j < TM->cols; ++j)\
            TM->entries[i][j].FIELD = (ARRAY) ? ARRAY[i][j] : 0;\
} while (0)

然后:

void tmatrix_set_prices (struct tmatrix *tm, double *prices[]) {
    TMATRIX_SET_2D_ARRAY(tm, price, prices);
}

void tmatrix_set_amts (struct tmatrix *tm, double *amts[]) {
    TMATRIX_SET_2D_ARRAY(tm, amt, amts);
}

这是一个糟糕的解决方案吗?我被告知过。我也被告知可以使用offsetof()来完成它,但它看起来更复杂,更难以使用。或者最好让entries成为数组而不是结构?实现这些功能的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

您可以使用设置struct tm的一个条目的函数来减少一些冗余逻辑。您可以在更高级别的功能中使用这些功能。

typedef void (*set_matrix_data_function)(struct tmatrix *tm, double *data[], int i, int j);

void set_matrix_price(struct tmatrix *tm, double *data[], int i, int j)
{
   tm->entries[i][j].price = (data) ? data[i][j] : 0;
}

void set_matrix_amt(struct tmatrix *tm, double *data[], int i, int j)
{
   tm->entries[i][j].amt = (data) ? data[i][j] : 0;
}

void tmatrix_set_data (struct tmatrix *tm, double *data[], set_matrix_data_function fun)
{
    for (int i = 0; i < tm->rows; ++i)
        for (int j = 0; j < tm->cols; ++j)
           fun(tm, prices, i, j);
}

void tmatrix_set_prices (struct tmatrix *tm, double *prices[])
{
   tmatrix_set_data(tm, prices, set_matrix_price);
}

void tmatrix_set_amts (struct tmatrix *tm, double *amts[])
{
   tmatrix_set_data(tm, prices, set_matrix_amt);
}

请注意,代码比仅使用两个函数更加庞大。只有当您需要更多数据成员才能处理时,这将获得回报。

答案 1 :(得分:1)

我没有对此进行过测试,但是如何在这些行中使用offsetof()

#include <stddef.h>

static void tmatrix_set_field(struct tmatrix *tm, double *vals[],
                              const size_t f_offset) {
    for (int i = 0; i < tm->rows; ++i)
        for (int j = 0; j < tm->cols; ++j)
            *(double *)(((char *)&tm->entries[i][j]) + f_offset) =
                 (vals) ? vals[i][j] : 0;
}

void tmatrix_set_prices (struct tmatrix *tm, double *prices[]) {
    tmatrix_set_field(tm, prices, offsetof(struct tmatrix_entry, price));
}

void tmatrix_set_amts (struct tmatrix *tm, double *amts[]) {
    tmatrix_set_field(tm, amts, offsetof(struct tmatrix_entry, amt));
}

你提到它“看起来更复杂”,但似乎可能不像宏那么复杂。

答案 2 :(得分:0)

我将专注于您向该结构的用户呈现的界面,而不是关注它在内部的实现方式。通过向结构的用户提供这两个函数,您可以在使宏的函数体调用传递给字段的名称或函数的调用之间来回切换,将函数的调用传递给该字段而没有波纹效果通过你的代码库。我同意这只是一种风格偏好。