Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 你能通过结构中的值进行枚举吗?_C - Fatal编程技术网

C 你能通过结构中的值进行枚举吗?

C 你能通过结构中的值进行枚举吗?,c,C,我知道,在定义枚举时,可以通过数字列表进行枚举: typedef enum MONTH { Jan = 1, Feb, March, ... }; 可以用同样的方法枚举结构中的值吗?我基本上希望使用for或while循环遍历结构中的值 struct items {char *item_name, int item_value}; struct items Items_list[] = { "item 1", 2000, "item 2", 3600, .... };

我知道,在定义枚举时,可以通过数字列表进行枚举:

typedef enum MONTH { Jan = 1, Feb, March, ... };
可以用同样的方法枚举结构中的值吗?我基本上希望使用for或while循环遍历结构中的值

struct items {char *item_name, int item_value};

struct items Items_list[] =
{ 
    "item 1", 2000,
    "item 2", 3600,
    ....
};
使用的语言是C


编辑:我可能刚刚回答了我自己的问题,因为我想到的是一个结构数组。但是,现在将保留该问题。

否,您不能迭代
结构的元素。最好是对循环中的
struct
的名称进行硬编码:

struct items *item = Items_list;

while (item < Items_list + sizeof(Items_list) / sizeof(*Items_list)) {
    printf("%s %d", item->item_name, item->item_value);
    ++item;
}

并且元素都是无序的和非连续的(即数字中存在间隙)。

否,您不能迭代
结构的元素。最好是对循环中的
struct
的名称进行硬编码:

struct items *item = Items_list;

while (item < Items_list + sizeof(Items_list) / sizeof(*Items_list)) {
    printf("%s %d", item->item_name, item->item_value);
    ++item;
}
并且元素都是无序的和非连续的(即数字中存在空白)。

此声明和初始值设定项组合无效。(在撰写此答案的原始版本时,问题发生了变化。)

如果您问“有没有一种方法可以访问结构的第一个成员,然后是第二个成员,而不知道结构元素的名称”,那么答案是“没有,不需要事先仔细编码”


仔细的编码涉及多个步骤。对于每个元素,您需要类型的编码、结构中成员的偏移量,以及成员的大小(如果类型的编码没有提供给您):

现在,您可以非常小心地编写代码来获取或设置特定指针指向的
结构项的第n个成员中的值。然而,这样做还远远不是小事

int get_int(const void *data, const MemberAccess *member)
{
    assert(member->type == MT_INT);
    return (*(const int *)((const char *)data + member->offset));
}
尽管有GCC,您仍需要转换为字符指针;您不能合法地在
void*
上执行指针算术

然后,您可以调用:

int value = get_int(&Items_list[1], &members[1]);
获取数组第二个元素的第二个字段的整数值

这是如此痛苦的处理,必须有很好的理由通过开销。可能有这样的原因。我知道一个系统有400个配置参数(这本身就是一个问题,但让我们假设这是可以的;它们已经积累了20多年的开发时间)存储在一个结构中,成员的类型是异构的。操纵它的代码被写了400次-哎哟因为它不使用类似于
MemberAccess
结构的系统。代码将比当前要紧凑得多,因为要处理的数据类型大约有十几种,所以大部分代码都是重复的。另一种降低代码复杂性的方法是将所有内容都转换成字符串,但这种转换也存在问题。

此声明和初始值设定项组合无效。(在撰写此答案的原始版本时,问题发生了变化。)

如果您问“有没有一种方法可以访问结构的第一个成员,然后是第二个成员,而不知道结构元素的名称”,那么答案是“没有,不需要事先仔细编码”


仔细的编码涉及多个步骤。对于每个元素,您需要类型的编码、结构中成员的偏移量,以及成员的大小(如果类型的编码没有提供给您):

现在,您可以非常小心地编写代码来获取或设置特定指针指向的
结构项的第n个成员中的值。然而,这样做还远远不是小事

int get_int(const void *data, const MemberAccess *member)
{
    assert(member->type == MT_INT);
    return (*(const int *)((const char *)data + member->offset));
}
尽管有GCC,您仍需要转换为字符指针;您不能合法地在
void*
上执行指针算术

然后,您可以调用:

int value = get_int(&Items_list[1], &members[1]);
获取数组第二个元素的第二个字段的整数值


这是如此痛苦的处理,必须有很好的理由通过开销。可能有这样的原因。我知道一个系统有400个配置参数(这本身就是一个问题,但让我们假设这是可以的;它们已经积累了20多年的开发时间)存储在一个结构中,成员的类型是异构的。操纵它的代码被写了400次-哎哟因为它不使用类似于
MemberAccess
结构的系统。代码将比当前要紧凑得多,因为要处理的数据类型大约有十几种,所以大部分代码都是重复的。另一种降低代码复杂性的方法是将所有内容都转换成字符串,但这种转换也存在问题。

不,没有简单的方法可以做到这一点。结构不是数值,因此不能循环遍历其值/成员。您可以使用数组而不是结构,并通过简单的for循环访问其成员,或者编写一个特殊的枚举器回调函数,该函数将结构作为一个参数,将数字作为另一个参数,并使用case或if语句查找结构的每个成员。

不,没有简单的方法可以做到这一点。结构不是数值,因此不能循环遍历其值/成员。您可以使用数组而不是结构并通过简单的for循环访问其成员,或者编写一个特殊的枚举器回调函数,该函数将结构作为一个参数,将数字作为另一个参数,并使用case或if语句查找结构的每个成员。

一种方法是,当您在内部结构中有一个指针类型,并且该指针不能有意义地为NULL时,执行如下操作:

for (int i=0; Item_List[i].item_name != 0; i++) {
   // do whatever
}
如果没有方便的指针类型,“sentinel”值通常可用于标记最后一条记录

您需要记住在结构数组的末尾添加一个null元素/sentinel