在我的项目中,我链接了 struct elem
的链接,每个 elem 都有许多不同的属性。
目前每次我想获得一个 elems 属性时,我都会调用一个函数,例如:
get_elem_address(&linked_list);
get_elem_this(&linked_list);
get_elem_that(&linked_list);
在每个函数中我都有相同的代码:
struct elem *elem = linked_list->first_elem;
while (elem != NULL) {
if (elem->identifer == identifer) get_elem_whatever_i_need;
elem = elm->next;
}
在某些函数中我可以保证标识符匹配的元素,在其他函数中我不确定。有没有一种方法可以编写一个函数来遍历链表并找到我想要的元素然后返回它。
我不确定我是否可以这样做的原因是因为在某些情况下它可能不是一个与传入的元素具有相同标识符的元素。
最佳答案
这个答案可能会从传统的 C 编程社区得到很多评论,也不太可能得到很多反对票,但我仍然会给出它。
您可以考虑使用函数式编程 方法。对于一个简单的链表,它可以说是矫枉过正,我个人(也)会坚持你给出的循环,但在更复杂的数据结构上,它绝对值得考虑。链表确实是一个很好的演示。
假设我们有以下链表:
#include <string.h>
typedef struct elem
{
struct elem * next;
char * identifier;
} t_elem;
然后我们可以编写一个通用的查找器函数,如下所示:
t_elem * find(t_elem * list, int (*sel)(t_elem * elem))
{
for (; list != NULL; list = list->next)
if (sel(list))
{
break;
}
return list;
}
它采用选择函数作为参数,在 C 编程中通常称为 回调 并返回列表中此函数返回非零值的第一个元素。查找具有特定标识符的第一个元素可能如下所示:
t_elem * find_id(t_elem * list, char * id)
{
int sel(t_elem * e)
{
return strcmp(e->identifier, id) == 0;
}
return find(list, sel);
}
上述函数是非标准 ANSI,因为它使用了嵌套函数。 GCC 支持这一点,因此我鼓励标准化委员会采用此类嵌套函数。
如果您想要或必须坚持使用标准 ANSI,那么您将必须像我在下面的示例中所做的那样,使所谓的闭包 显式化。在这种情况下,闭包仅包含参数 id
,但通常必须定义专用的 struct
。闭包作为 void
指针传递,并在使用时转换为适当的类型(确实容易出错)。
t_elem * find2(t_elem * list, int (*sel)(t_elem * elem, void *), void * cl)
{
for (; list != NULL; list = list->next)
if (sel(list, cl))
{
break;
}
return list;
}
int sel_id(t_elem * e, void * cl)
{
char * id = cl;
return strcmp(e->identifier, id) == 0;
}
t_elem * find_id2(t_elem * list, char * id)
{
return find2(list, sel_id, id);
}
如果您对这种方法感到满意当然取决于您,但对我来说它已成为一种标准工具。
关于c - 如何减少 C 代码中的代码重复(由于空指针而不确定),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16940257/