此循环将崩溃并在 XCode 4.6.2 中给出 EXC_BAD_ACCESS 的错误
这是循环代码
for (beforeToDel = studentToChange->pFirstClass;
(int)strcmp(beforeToDel->pNext->classId, className) == 0;
beforeToDel = beforeToDel->pNext)
{}
并且不同的变量具有这些值:
非常感谢您提供的任何帮助!
此循环将崩溃并在 XCode 4.6.2 中给出 EXC_BAD_ACCESS 的错误
这是循环代码
for (beforeToDel = studentToChange->pFirstClass;
(int)strcmp(beforeToDel->pNext->classId, className) == 0;
beforeToDel = beforeToDel->pNext)
{}
并且不同的变量具有这些值:
非常感谢您提供的任何帮助!
beforeToDel->pNext->pNext
是NULL
。您的循环将在第二次迭代时崩溃,试图通过该指针间接比较到className
. 您需要在调用之前检查它strcmp
。
旁白:为什么要进行类型转换int
?
strcmp
转换为int
. 已经是一个了。beforeToDel
是 NULL,或者如果beforeToDel->pNext
是 NULL,会发生什么?如果他们没有指向任何东西,那么他们就不能有classId
orpNext
成员,对吧?strcmp
如果您没有包含,则使用它是错误的<string.h>
,因此请确保您已包含它。我假设您正在寻找指向要删除的节点的链接,因此使用了相当尴尬的标识符“beforeToDel”。如果列表的头部是您要删除的节点会发生什么?为什么不从指向studentToChange->pFirstClass
链接而不是节点的指针开始并对其进行迭代?这将解决您的头部问题,同时使您的代码更加清晰。
我将像这样声明我的链表:
struct list {
struct list *next;
char class_name[];
};
声明一个指向任何类型的指针pNext
。调用它link
,因为该对象将存储指向代码将更新的链接的指针。将其初始化为列表的头部。这样,当第一次迭代导致匹配时,您将轻松更改列表的头部。在我的功能中,我将返回新的头部。您无需在代码中执行此操作。只需确保link
指向列表的头部(例如link = &studentToChange->pFirstClass;
)。
在每次迭代结束时,更新link
以指向(*link)->next
(或pNext
,在您的情况下)。
操作*link
,而不是link
(例如strcmp(*link->classId, class_name) == 0
)。当找到要删除的节点时,通过 using*link = *link->next;
或等效项在其顶部分配。
struct list *list_remove_class_name(struct list *head, char *class_name) {
struct list **link = &head;
/* Did you mean != 0 here? */
while (*link != NULL && strcmp(*link->class_name, class_name) == 0) {
*link = *link->next;
}
struct list *node = *link;
if (node != NULL) {
*link = node->next;
}
free(node);
return head;
}