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