c-从链表中删除元素时出现异常



我试图从链接列表中删除一个单词(char*value(,但当我将我的单词与链接列表节点单词进行比较时,遇到了异常。

EXC_BAD_ACCESS(代码=1,地址=0xa00000002(

我不知道为什么会发生这种情况,如果能找到这个问题的任何解决方案,我将不胜感激。

LinkedList* DeleteWordElement(LinkedList* head, char* value){
LinkedList *previous=head, *current=head->next;
if (head == NULL)
return head;
if (head->data == value) 
{
LinkedList *temp = head;
head = head->next;
free(temp);
return head;
}
while (previous!=NULL)
{
if (previous->data == value) // Exception
break;
current = previous;
previous = previous->next;
}
if (previous != NULL)
current->next = previous->next;
free(previous);
return head;
}

操作前:

LinkedList *previous=head, *current=head->next;

您需要检查head是否为NULL。然后应该使用strcmp而不是==来比较C字符串value:

strcmp比较实际的C字符串内容,同时在两个C字符串询问这两个字符指针是否指向同一个位置(来源(

最后,您不需要保留previous指针,current->next指针就足够了:

LinkedList* DeleteWordElement(LinkedList* head, char* value){
if (head == NULL)
return head;
if (strcmp(value, head->data) == 0){
LinkedList *next = head->next;
free(head);
return next;
}
LinkedList *current=head;
while (current->next != NULL){
if (strcmp(value, current->next->data) == 0){
LinkedList *next = current->next;
current->next = current->next->next;
free(next);
break;
}
current = current->next;
}
return head;
}

如果使用递归版本,代码可以缩短,尽管这会以性能为代价:

LinkedList* DeleteWordElement(LinkedList* current, char* value){
if(current != NULL){
if (strcmp(value, current->data) == 0){
LinkedList *result = current->next;
free(current);
return result;
}
current->next = DeleteWordElement(current->next, data);
}
return current;
}

As已经在另一个答案和注释部分指出,表达式

current=head->next

当CCD_ 8。

另一个问题是表达式

head->data == value

不比较实际的字符串内容,而是比较指针本身(即内存地址(。这不是您想要的,因为指针可能总是不同的,即使字符串内容相同。为了比较实际的字符串内容,必须使用函数strcmp

另一个答案已经包含了问题的解决方案。然而,我想提供一种替代解决方案,它对计算机来说更短、更高效,但对程序员来说可能更难理解,因为它使用双指针(即指针对指针(:

LinkedList* DeleteWordElement( LinkedList *head, char* value )
{
LinkedList **pp = &head, *p;
while ( (p=*pp) != NULL )
{
if ( strcmp( p->data, value ) == 0 )
{
//found node, so unlink and remove it
*pp = p->next;
free( p );
break;
}
pp = &p->next;
}
return head;
}

正如您所看到的,此解决方案只需要一个if语句,而您的答案中的代码需要4个if语句,而另一个答案需要3个if语句。当使用双指针时,这些额外的if语句是不必要的,因为相同的代码可以处理所有情况。因此,您不需要为每个案例引入额外的代码路径。因此,此解决方案也不需要代码重复。

还值得一提的是,函数签名

LinkedList* DeleteWordElement(LinkedList* head, char* value)

效率有点低。返回值是新的头,因此调用函数的代码必须根据返回值更新列表头。如果调用函数的代码只传递列表头指针的地址,那么会更简单,这样函数就可以在必要时更新列表头本身。这样,调用函数的代码就不必做任何额外的工作。

为了实现这一点,您可以将函数签名更改为以下内容:

void DeleteWordElement( LinkedList** pp_head, char* value )

因为指针的地址是指向指针的指针(即双指针(,所以现在必须使用**而不是仅使用*

此外,现在您不再使用函数的返回值,您可能希望将其用于其他用途。例如,您可能希望函数返回是否找到该值。因此,您可能需要将签名更改为以下内容:

bool DeleteWordElement( LinkedList** pp_head, char* value )

现在您可以在找到值时使函数return true,否则return false表示未找到值。请注意,必须使用#include <stdbool.h>才能访问booltruefalse

尽管我们通过添加布尔返回值使函数更加强大,但它和以前一样简单。

bool DeleteWordElement( LinkedList **pp_head, char* value )
{
LinkedList **pp = pp_head, *p;
while ( (p=*pp) != NULL )
{
if ( strcmp( p->data, value ) == 0 )
{
//found node, so unlink and remove it, and then return true
*pp = p->next;
free( p );
return true;
}
pp = &p->next;
}
//return false because we did not find any matching node in the list
return false;
}

相关内容

  • 没有找到相关文章

最新更新