Поиск события в связанном списке - PullRequest
1 голос
/ 25 января 2020

Я пытаюсь найти односвязный список, который может содержать событие (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)->next = *current;). Я не могу понять, почему назначение следующего предыдущего значения приводит к завершению программы.

ПРИМЕЧАНИЕ: структура и параметры для srchevent(...) не могут быть изменены.

1 Ответ

1 голос
/ 26 января 2020

Использование двойных указателей внутри функции может быть медленным и проблематичным c. Лучше использовать одиночные указатели и установить возвращаемые значения в конце.

Поскольку вы устанавливаете все три возвращаемых значения в NULL вверху (например, *previous = NULL), следующее приведет к ошибке:

(*previous)->next = *current;

Другими словами, вы пытаетесь разыменовать нулевой указатель. Аналогично для pprevious. Если бы вы скомпилировали с опцией -g и использовали gdb, она бы уловила ошибку и выдала вам сообщение.

Обратите внимание, что next для каждого узла уже настроено в связанном список, поэтому не необходимо установить / изменить его.

Кроме того, логи c могут быть упрощены [и это может быть частью проблемы].

Вот переработанная версия:

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;
}
...