English 中文(简体)
改变不同结构的共同领域的必要性
原标题:Need way to alter common fields in different structs
  • 时间:2009-09-18 17:06:02
  •  标签:

这里为Windows和各种幻灯平台设计一米。 我有一套共同的领域,但也有不同的领域。 例如:

typedef struct {
    char street[10];
    char city[10];
    char lat[10];
    char long[10];
} ADDR_A;

typedef struct {
    char street[10];
    char city[10];
    char zip[10];
    char country[10];
} ADDR_B;

显然,它们只是简单,我实际上有6个不同的构件,但这符合基本的想法。

我所希望的是,我可以通过这一职能向其中之一发出一点意见,并能够更新共同领域。 类似:

static void updateFields( void *myStruct ) {
    strcpy( myStruct->street, streetFromSomethingElse );
    strcpy( myStruct->city, cityFromSomethingElse );
}

而我所写的是,由于空白点和某种形式,我没有做什么工作,但确实没有一种很好的方法可以做到这一点(如果有的话)。 我不反对另外一种论点,即某些方面具体规定了结构类型。

出于不相关的原因,国际大西洋、印度洋、地中海和南印度洋金枪鱼委员会改变这些结构,或将这些结构或与它们做任何事情。 I HAVE使用这些设备。

一如既往,事先得到帮助。

EDIT:正如我在下文的评论中所补充的那样,共同的领域是保证在一开始或全部到底,或者在其他情况下。 他们的存在得到保障。

最佳回答

考虑到这些结构至少没有类似的布局,实现这一目的的途径有限,既不短也不高:

  1. www.un.org/Depts/DGACM/index_spanish.htm 使用 has片,而不是堆积你的数据。 这样做将使得能够使用其名称作为清点的关键的田地,而不论实际类型如何。 这需要在C造成大量麻烦,而且只有你能够说出100个领域,我才会建议。

  2. www.un.org/Depts/DGACM/index_spanish.htm 严格打字和更新领域,具体如下:。 Yeah是你不希望的,但对于一定数量的田地来说,这可能是ok的。

  3. www.un.org/Depts/DGACM/index_spanish.htm 采用“所建议的宏观方法。 然而,我认为,尽可能避免宏观。 这是值得的。

象C那样做的事情并不容易,也不好(没有 d打)。 这是一种典型的例子,一种动态的语言会更加舒适(也许你可以把 p从你的法典中说出来吗?) iii

问题回答

参数规则――仅可说明最低结构――可以适用。

static void updateStreetAndCity ( char *street, char *city ) {
    strcpy( street, streetFromSomethingElse );
    strcpy( city, cityFromSomethingElse );
}

你们不得不用两个点而不是一个点来提一下它,但是它符合一个功能的议案,这一职能将针对你们的所有结构类型开展工作。

如果你的工作范围不同,你可以采用宏观方法,如C99的数学数字,提供静态的多变性,但这项工作范围很广。

#define ASSIGN(type,object,member,value) do { 
    ((type *)object)->member = value; 
    } while (0)

现在,你可以做像:

#include <stdio.h>

struct foo {
    int x;
    char y;
};

struct bar {
    char y;
    int x;
};

int main () {
    struct foo foo;
    struct bar bar;
    ASSIGN(struct foo, &foo, x, 100);
    ASSIGN(struct bar, &bar, y,  x );
    // ...
}

当然,你可以永远扩大这一范围,以纳入一项职能呼吁,以开展这项业务,从而支持<代码>memcpy或strcpy,或者类似操作是三角的。

这是我plC++的时候,因为这是对多吗? 或模板。 或超负荷运行。

然而,如果所有共同领域都首先如此,你就应当能够把点推到“<条码>。 ADDR_A,并按此办理:

static void updateFields( void *myStruct ) {
    ADDR_A *conv = myStruct;
    strcpy( conv->street, streetFromSomethingElse );
    strcpy( conv->city, cityFromSomethingElse );
}

如果阿达姆酒吧建议不工作,你可以采用宏观方法。

#define UPDATE_FIELDS( myStruct, aStreet, aCity ) 
  strcpy( myStruct->street, aStreet ); 
  strcpy( myStruct->city, aCity );

但是,C++的插图较好;

只要你希望更新的部分是每个结构的共同预设点,你就可以确定一个新结构,列出这些预设领域,并据此计算其参数。 假设你所创造的固定结构的布局是相同的(即,没有奇怪的编纂者回避问题),更新后将对所有结构进行预先确定的工作。

Edit:As sztomi正确地指出,只要田间相对被抵消,你就可以接触非固定部分。 然而,我仍然倾向于设立一个共同结构,作为这一职能的“典型”;它防止在你可能选择的任何其他机构中改变外地名称。

只是一个未经测试的想法:

struct ADDR_X_offset {
  int street;
  int city;
} ADDR_A_offset = { offsetof(ADDR_A,street), offsetof(ADDR_A,city) },
  ADDR_B_offset = { offsetof(ADDR_B,street), offsetof(ADDR_B,city) };

static void updateFields( void *myStruct, struct ADDR_X_offset *offset ) {

    strcpy( myStruct+offset->street, streetFromSomethingElse );

    strcpy( myStruct+offset->city,   cityFromSomethingElse );

}

尚未提及的一种选择是,利用<>toffsetof(<>/code>, 宏观从<stddef.h>,为这些领域设立说明员。 然后,你可以向修改职能提供适当的说明。

typedef struct string_descriptor
{
    size_t offset;
    size_t length;
} string_descriptor;

在C99,你可以这样做:

int update_string(void *structure, const string_descriptor d, const char *new_val)
{
    char *buffer = (char *)structure + d.offset;
    size_t len = strlen(new_val);
    size_t nbytes = MIN(len, d.length);
    // Optionally validate lengths, failing if the new value won t fit, etc
    memcpy(buffer, new_val, nbytes);
    buffer[nbytes] =   ;
    return(0);  // Success
}

void some_function(void)
{
    ADDR_A a;
    ADDR_B b;
    static const string_descriptor a_des =
        { .offset = offsetof(ADDR_A, street), .length = sizeof(a.street) };
    static const string_descriptor b_des =
        { .offset = offsetof(ADDR_B, street), .length = sizeof(b.street) };

    update_string(&a, a_des, "Regent St."); // Check return status for error!
    update_string(&b, b_des, "Oxford St."); // Check return status for error!
}

显然,就单一类型而言,这看着迷惑,但经过仔细的概括,你可以使用多个描述器,描述器可以更大(更加复杂),但可以参考,只需要一度界定。 可在两个结构中的任何一个领域更新<代码>。 trick计是长效初始器sizeof(b.street);我认为,需要一个准确的类型变量,以提供正确的信息,但我很乐意作出(Standard C99)修订,以取消这一限制。 非部委通用说明器可以包含一种可能相关的类型指标和成员名称及其他信息,尽管有人要加以阐述,但我却倾向于建立非常简单的结构。 你们可以利用职能点提供不同的验证,以证实不同的特性,即对纬度和长度的验证与对街道名称的确认有很大不同。

你还可以写出各种文字说明和多种更新功能。 例如,在ADDR_A和AADDR_B领域,你可以有一系列的描述,然后通过一系列新的理论等,通过这些领域的新价值。

你们有责任使描述者正确,使用正确的描述。


另见:。 __builtin_offsetof营运人的目的和返回类型是什么?

如果你能够以任何方式改变结构,我认为,这种结构的通过是一个好的想法。 发挥一刀切的作用,并掌握地址。

int updateStreetAndCity(void *addr, int type);
double getLatitude(void *addr, int type);

等等。 你们可以有一面或数种宏观定义来说明这些类型。 然后,在每项职能中,根据你所穿的类型,指定另一个专门从事这些工作的职能(以避免出现1 000件不同事情的mon子开关说明)。

如果你没有通过哪类建筑(如你提出的空白*),那么你基本上就注定了。 他们只是一.一角的记忆。

你可以做的是拥有多个函数,比如你建议的update_fields,并根据结构类型调用正确的函数(这很容易,在宏中可以隐蔽一些语法噪音)。

下面是:

#include <stdio.h>
#include <string.h>

typedef struct {
    char street[10];
    char city[10];
    char lat[10];
    char lon[10];
} ADDR_A;

typedef struct {
    char street[10];
    char city[10];
    char zip[10];
    char country[10];
} ADDR_B;

#define UPDATEFIELDS(type, value) updateFields_##type(value)

static void updateFields_ADDR_A(ADDR_A *myStruct ) {
        strcpy(myStruct->street, "abc" );
        strcpy(myStruct->city, "def" );
    }

static void updateFields_ADDR_B(ADDR_B *myStruct ) {
        strcpy(myStruct->street, "abc" );
        strcpy(myStruct->city, "def" );
    }

int main(){
    ADDR_A a;
    ADDR_B b;

    updateFields_ADDR_A(&a);
    updateFields_ADDR_B(&b);
    UPDATEFIELDS(ADDR_A, &a);

    printf("%s
", a.city);
    printf("%s
", b.city);
}

通知你显然不应在更新时写出实际的外地变化代码 外地 三十项职能,但只是使用该守则作为包裹,以便正确冲抵内地。

我也想使你能够再次使用宏观方法的地方化。

#define COMMONBODY strcpy(myStruct->street, "abc" );
        strcpy(myStruct->city, "def" );


static void updateFields_ADDR_A(ADDR_A *myStruct ) {
    COMMON_BODY
    }

static void updateFields_ADDR_B(ADDR_B *myStruct ) {
    COMMON_BODY
    }

或甚至将共同守则单独列入档案,并将其列入两倍(不寻常,但工作档案)

static void updateFields_ADDR_A(ADDR_A *myStruct ) {
    #include "commonbody.c"
    }

static void updateFields_ADDR_B(ADDR_B *myStruct ) {
    #include "commonbody.c"
    }

几乎也可以(但我知道的)使用<typeof的操作者,但名称左部分除外。

如果你的结构规模不同,我们甚至只能使用一个更新的实地功能(无效*),这种功能将结构的规模作为第二个参数,并用于自动投放到正确的类别。 它非常 d,但可能[如果有人想看到这一解决办法得到发展,请评论]。

也可以使用工会。 如果存在共同的预先规定,任何工会成员都可以进入共同的领域(但我的理解是不是这样)。 你们必须认识到,界定这种结合并不改变现有数据结构。 这基本上界定了“ADDR_A”或“ADDR_B”的类型,而不是使用点子。

typedef union {
    ADDR_A a;
    ADDR_B b;
} ADDR_A_or_B;

如果存在共同的预先规定,你可以利用任何准入领域确定这些变量:

static void updateFields(ADDR_A_or_B *myStruct ) {
    strcpy( myStruct->a.street, someStreeValueFromSomewhereElse);
    strcpy( myStruct->a.city, someCityValueFromSomewhereElse);
}

在呼吁时,你才需要:

ADDR_A a;
updateFields((ADDR_A_or_B *)&a);

ADDR_B b;
updateFields((ADDR_A_or_B *)&b);
typedef struct {
    char street[10];
    char city[10];
} ADDR_BASE;

typedef struct {
    struct ADDR_BASE addr;
    char lat[10];
    char long[10];
} ADDR_A;

typedef struct {
    struct ADDR_BASE addr;
    char zip[10];
    char country[10];
} ADDR_B;

这样,你就可以将ADDR-BASE* 传给你。





相关问题
热门标签