我正在尝试消除链表中所有重复元素的出现。 例如,如果我有:1-2-3-2-4-2-4,我想消除所有出现的2和4并得到:1-3
我使用一个名为eliminateRepeated
的函数来迭代并计算出现次数;如果计数大于1,程序将调用函数eliminateAllTheOc
。但我明白了:1-3-2-4。最后一次出现没有消除。
例如,如果我单独使用值4调用函数eliminateAllOc
,它可以正常工作并返回1-2-3-2-2。
typedef struct{
int num;
}t_dataL;
typedef struct s_nodeL{
t_dataL dataL;
struct s_nodeL *next;
}t_nodeL;
typedef t_nodeL *t_list;
int elimnateAllTheOc(t_list *l, t_dataL *d, int(*cmp)(const void*, const void*)){
if(!*l) return 0;
t_nodeL *aux;
while(*l){
if(cmp(&(*l)->dataL, d) == 0){
aux = *l;
*l = (*l)->next;
free(aux);
}
else l = &(*l)->next;
}
return 1;
}
int eliminateRepeated(t_list *l, int(*cmp)(const void*, const void*)){
t_list *plec, *ini = l;
t_nodeL *aux;
int n = 0;
while (*l){
plec = ini;
while(*plec){
if(cmp(&(*l)->dataL, &(*plec)->dataL) == 0) n++;
plec = &(*plec)->next;
}
if(n > 1) eliminateAllTheOc(ini, &(*l)->dataL, cmp);
else l = &(*l)->next;
n = 0;
}
return 1;
}
如何消除所有重复元素的出现?
答案 0 :(得分:1)
首先,你必须修正错误的功能名称,即
int elimnateAllTheOc(... -> int eliminateAllTheOc(
^
然后,您必须修复代码所具有的未定义行为。问题是您将指针传递给比较值,即t_dataL *d
。这是一个指向您要释放的列表元素内的数据的指针。因此,一旦释放元素,解除引用d
就是未定义的行为。
示例强>
考虑一个非常简单的清单:
1 -> 1
在这种情况下,您要删除这两个元素。使用指向第一个元素的指针调用eliminateAllTheOc
,并使用比较值将指针传递给第一个元素中的dataL
。
在第一个循环中释放第一个元素。因此d
不再指向有效对象。因此,在您的下一个循环中,您在执行*d
时会有未定义的行为。
如果要将指针传递给比较值,则必须确保指针始终指向有效对象。你可以通过复制来做到这一点:
if(n > 1)
{
t_dataL tmp = (*l)->dataL;
eliminateAllTheOc(ini, &tmp, cmp);
}
else l = &(*l)->next;
我怀疑这解决了代码的所有问题,但修复此UB是第一个重要步骤。