这个答案可能会得到传统 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);
}
如果您对这种方法感到满意,当然取决于您,但对我来说,它已成为一种标准工具。