-3

此循环将崩溃并在 XCode 4.6.2 中给出 EXC_BAD_ACCESS 的错误

这是循环代码

for (beforeToDel = studentToChange->pFirstClass; 
     (int)strcmp(beforeToDel->pNext->classId, className) == 0;
     beforeToDel = beforeToDel->pNext)
     {}

并且不同的变量具有这些值:

在此处输入图像描述

非常感谢您提供的任何帮助!

4

2 回答 2

2

beforeToDel->pNext->pNextNULL。您的循环将在第二次迭代时崩溃,试图通过该指针间接比较到className. 您需要在调用之前检查它strcmp

旁白:为什么要进行类型转换int

于 2013-04-26T04:27:42.600 回答
0
  1. 无需将 的返回值强制strcmp转换为int. 已经是一个了。
  2. 如果beforeToDel是 NULL,或者如果beforeToDel->pNext是 NULL,会发生什么?如果他们没有指向任何东西,那么他们就不能有classIdorpNext成员,对吧?

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;
}
于 2013-04-26T05:21:11.077 回答