【问题标题】:Searching for Event in Linked List在链表中搜索事件
【发布时间】:2020-01-25 20:04:58
【问题描述】:

我正在尝试搜索可能包含事件 (int) 的单链表。我需要跟踪当前正在处理的节点和它之前的两个节点(需要处理)。

代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct node {
    int eventnum;
    int eventfq;
    struct node *next;
} node;

void insertevent(node **list, int event);
void srchevent(node *list, int xevent, node **current, node **previous, node **pprevious);

int main() {
    node *list = NULL;
    int i = 0;
    for(i = 0; i < 10; i++) {
        insertevent(&list, i);
    }
}

void insertevent(node **list, int event) {
    node *newnode = (node *)malloc(sizeof(node));
    node *current, *previous, *pprevious;
    srchevent(*list, event, &current, &previous, &pprevious);
}

void srchevent(node *list, int xevent, node **current, node **previous, node **pprevious) {
    *pprevious = *previous = NULL;
    *current = list;

    printf("current:\naddr:%d\nval:%d\n\n", &current, current);
    printf("previous:\naddr:%d\nval:%d\n\n", &previous, previous);
    printf("pprevious:\naddr:%d\nval:%d\n\n", &pprevious, pprevious);
    (*previous)->next = current;

    /* nothing past here executes */
    printf("current:\naddr:%d\nval:%d\n\n", &current, current);
    printf("previous:\naddr:%d\nval:%d\n\n", &previous, previous);
    printf("pprevious:\naddr:%d\nval:%d\n\n", &pprevious, pprevious);
    (*pprevious)->next = *current;
}

输出:

adding 0
current:
addr:6422216
val:6422248

previous:
addr:6422220
val:6422244

pprevious:
addr:6422224
val:6422240

此代码应在列表中插入 10 个节点(插入功能尚未实现)。但是,执行在第 34 行结束 ((*previous)-&gt;next = *current;)。我不明白为什么分配上一个的下一个值会导致程序结束。

注意:srchevent(...) 的结构和参数不能更改。

【问题讨论】:

  • 阅读How to Askminimal reproducible example。发布您的输入和结果输出。
  • 使用调试器和/或改进您的调试语句。至少,使用调试器或printf 检查所有指针值。您可能会发现一个或多个指针为 NULL 或无效。无论如何,我们无法调试不完整的代码,需要minimal verifiable example,如前所述。
  • 感谢您的提示,已尝试实施您的建议

标签: c pointers singly-linked-list


【解决方案1】:

在函数中使用双指针可能会很慢而且有问题。最好使用单指针并在最后设置返回值。

由于您将所有三个返回值都设置为顶部的NULL(例如*previous = NULL),因此以下将出现段错误:

(*previous)->next = *current;

换句话说,您正在尝试取消对空指针的引用。同样适用于pprevious。如果您使用-g 选项编译并使用gdb,它会发现错误并给您一条消息。

请注意,每个节点的next 已在链表中设置,因此您应该不需要设置/更改它。

此外,逻辑可以简化 [这可能是问题的一部分]。

这是一个重构版本:

void
srchevent(node *list, int xevent,
    node **current, node **previous, node **pprevious)
{
    node *cur;
    node *prev = NULL;
    node *pprev = NULL;

    for (cur = list;  cur != NULL;  cur = cur->next) {
        if (cur->eventnum == xevent)
            break;
        pprev = prev;
        prev = cur;
    }

    *current = cur;
    *previous = prev;
    *pprevious = pprev;
}

【讨论】:

  • 您的解决方案效果很好,而且比我的要优雅得多。我将不得不阅读更多关于指针/引用的内容——C 不是我的母语编程语言。我以前没有使用过 gdb,但这听起来像是我必须学习的东西。我目前正在使用不带调试器的 Minix,所以也许我会先在有 gdb 的系统上编程。
  • 您可能会升级到 linux(我从 1993 年就开始使用它,所以我强烈推荐它)。您必须备份文件并在安装后恢复它们,但 linux 在大多数硬件上运行良好,甚至有些旧的硬件
  • 如果可以的话,我会换掉,但我在操作系统课程中使用 Minix,所以我别无选择,但感谢您的推荐!
猜你喜欢
  • 2020-04-15
  • 2013-07-20
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 2021-02-19
  • 2016-12-09
  • 1970-01-01
相关资源
最近更新 更多