C代码功能中的分割故障


struct Node {
    char gender;
    int turns_in_bathroom;
    struct Node *next;
};
struct Queue {
    struct Node *front, *back;
};
int QueueDeleteNext(Queue *myQueue, char value) {
Node *current_node, *previous_node;
previous_node = NULL;
int found = 0;
for (current_node = myQueue->front; current_node != NULL;
     previous_node = current_node, current_node = current_node->next) {
    if (current_node->gender == value) {
        if (previous_node == NULL) {
            myQueue->front = myQueue->back = NULL;
        }
        else {
            previous_node->next = current_node->next;
            if(previous_node->next == NULL){
                myQueue->back = previous_node;
            }
        }
        free(current_node);
        found = 1;
    }
}
return found;
}

我在线上得到了分割故障

if (current_node->gender == value) {

我一生都不能弄清楚原因。这里发生了什么?更不用说尽管我的调试器出现故障错误,该代码仍将一直通过。不过,我认为有些错误可能与此有关,我想确保我已经涵盖了所有基础。

显然已经解决了问题,但代码仍然存在问题:

  • 条件(previous_node == NULL)测试当前节点是否是队列的头部。在这种情况下,必须将头部涂抹,而不是先前的节点的next,但是代码在不正确删除可能的尾随eNodes的情况下将整个队列提示。

  • 当删除队列中的最后一个节点时,应更新队列的背部,以便随后的推动可以附加到结尾。

最后,看起来OP的意图是删除具有相应值的所有节点的意图,因为执行在第一个删除后没有停止。因此,让我们这样做并返回已删除的节点的数量:

int QueueDeleteNext(struct Queue *q, char value)
{
    struct Node *prev = NULL;
    struct Node *curr = q->front;
    int count = 0;
    while (curr) {
        if (curr->gender == value) {
            struct Node *nn = curr;
            if (prev == NULL) {
                q->front = curr->next;
            } else {
                prev->next = curr->next;
            }
            if (curr == q->back) q->back = prev;
            curr = curr->next;
            free(nn);
            count++;
        } else {
            prev = curr;
            curr = curr->next;
        }
    }
    return count;
}

主循环现在是while循环,可以以不同的方式对待删除和跳过节点。在两种情况下,下一个节点是curr->next,但是当删除节点时,prev节点保持不变!此代码还保留了队列的背面。

实现此目的的另一种方法是使用用于节点指针的指针,而不是使用prev指针。这消除了区分头和其他节点的需求。nd首先是队列头的地址,也是上一个节点的'next field after that. The code updates the pointer that points to the current node via nd`:

的地址
int QueueDeleteNext(struct Queue *q, char value)
{
    struct Node **nd = &q->front;
    int count = 0;
    q->back = NULL;
    while (*nd) {
        if ((*nd)->gender == value) {
            struct Node *nn = *nd;
            (*nd) = (*nd)->next;
            free(nn);
            count++;
        } else {
            q->back = *nd;
            nd = &(*nd)->next;
        }            
    }
    return count;
}

此代码可以扩展到仅删除第一个节点或第一个_n_nodes。

for (current_node = myQueue->front; current_node != NULL;
 previous_node = current_node, current_node = current_node->next)

在循环的每次迭代结束时,您要求Current_Node指向其下一个元素。但是,下面的一些行:

free(current_node);

您释放了此节点。因此,它不再指向任何分配的东西,从而导致您以后会遇到的细分错误。只需在找到要删除的元素时退出功能:

int QueueDeleteNext(Queue *myQueue, char value) {
Node *current_node, *previous_node;
previous_node = NULL;
for (current_node = myQueue->front; current_node != NULL;
     previous_node = current_node, current_node = current_node->next) {
    if (current_node->gender == value) {
        if (previous_node == NULL) {
            myQueue->front = myQueue->back = NULL;
        }
        else {
            previous_node->next = current_node->next;
            if(previous_node->next == NULL){
                myQueue->back = previous_node;
            }
        }
        free(current_node);
        return 1;
    }
}
return 0;
}

uth = 1后添加返回语句;阻止了调试器丢弃错误。

相关内容

  • 没有找到相关文章

最新更新