1

在我的项目中,我链接了 的链接,struct 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;
}

在某些功能中,我可以保证会有一个标识符匹配的元素,在其他功能中我不确定。有没有办法可以编写一个函数来遍历链表并找到我想要的元素然后返回它。

我不确定我是否能做到这一点的原因是因为它可能不是一个元素与传入的元素具有相同的标识符。

4

1 回答 1

1

这个答案可能会得到传统 C 编程社区的很多评论,也不太可能得到很多反对票,但我仍然会给出它。

您可以考虑使用函数式编程方法。对于一个简单的链表,它可以说是矫枉过正,我个人(也)会坚持你给的循环,但在更复杂的数据结构上,它绝对值得考虑。链表确实是一个很好的演示。

所以让我们假设我们有以下链表:

#include <string.h>

typedef struct elem
{
        struct elem     * next;
        char            * identifier;
} t_elem;

然后我们可以编写一个通用的finder函数,如下所示:

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);
}

如果您对这种方法感到满意,当然取决于您,但对我来说,它已成为一种标准工​​具。

于 2013-06-05T14:57:33.980 回答