Я реализую связанный список в C со структурой
struct node
{
int data;
struct node *next;
};
Я написал функцию добавления для добавления узла в конец связанного списка, как показано ниже, и функцию отображения для отображения всех узлов. Но я думаю, что дисплей дает ошибку сегментации из-за некоторой несогласованности в функции добавления. Что здесь может быть не так? В моей книге есть аналогичная функция для добавления с использованием malloc. Я хочу знать, что не так в моей функции.
void append(struct node **q, int d)
{
struct node *temp;
temp = *q;
printf("\nBegin: Address at temp = %u", temp);
while (temp!= NULL){
temp = temp->next;
printf("\nTravel: Address at temp = %u", temp);
}
struct node p1;
p1.data = d;
p1.next = NULL;
*q=&p1;
printf("\nEnd: Address at *q = %u\n", *q);
printf("\n*q->data = %d next = %u", (*q)->data,(*q)->next );
}
void display(struct node *q)
{
printf("\n");
while (q != NULL){
printf(" -> %d",q->data);
q = q->next;
}
}
int main(int argc, char *argv[])
{
struct node *p;
p = NULL; /* empty linked list */
printf("\nNo. of elements in the Linked List = %d", count(p));
append(&p,1);
display(p);
append(&p,2);
display(p);
printf("\nNo. of elements in the Linked List = %d", count(p));
}
Выход:
No. of elements in the Linked List = 0
Begin: Address at temp = 0
End: Address at *q = 6684096
*q->data = 1 next = 0
-> 1Segmentation fault
Однако, когда я заменяю
struct node p1;
p1.data = d;
p1.next = NULL;
*q=&p1;
с
temp = *q;
*q = malloc(sizeof(struct node))
temp->data = d;
temp->next = NULL;
ошибка исчезла.
Кто-нибудь может объяснить причину?
@Юннош. Извини за это. Мое редактирование и ваш ответ пришли параллельно. Я пробовал разные вещи и нашел точное утверждение, в котором я мог ошибиться, поэтому отредактировал пост, а затем увидел ваш ответ, который прояснил мое замешательство. Так что я тоже принял ваш ответ. Если это вас оскорбляет, я могу вернуть свою правку.
"обидеть" - это слишком сильно. И в этом случае, я думаю, все обошлось. Нет необходимости возвращаться. С другой стороны, пожалуйста, поймите недооцененную концепцию вопроса о движущейся цели и по возможности избегайте ее. Да, я вижу, что редактирование и мой ответ (особенно версии...) имеют некоторое правдоподобное совпадение. Это нормально. Не беспокойся. (радостно играю с моим новым блестящим 25 повторением... :-))
Здесь вы используете адрес локальной переменной таким образом, чтобы сделать ее доступной после выхода из функции:
*q=&p1;
Затем вы покидаете функцию.
Всякий раз, когда к нему обращаются позже, он будет обращаться к памяти, которая больше НЕ является локальной переменной.
Вам нужно выделить память для переменной. Используйте malloc()
для этого.
Например.:
struct node *p1;
p1 = malloc(sizeof(*p1));
/* skipping recommended check of success/NULL */
p1->data = d;
p1->next = NULL;
*q=p1;
Есть и другие проблемы, например, вы позволяете списку начинаться с нового узла, за которым следует NULL, что приводит к потере/утечке всего вашего предыдущего списка. Но непосредственная проблема вызвана ссылкой на место в памяти ушедшей локальной переменной после того, как она существует.
по поводу петли:
while (temp!= NULL){
Это приводит к тому, что temp
содержит NULL
, поэтому он прошел весь связанный список и вышел за его конец.
Предлагать:
while (temp->next != NULL){
так как это перестанет проходить через связанный список, когда он указывает на последний «узел» в связанном списке.
Затем нужно использовать temp
в качестве указателя на последний «узел» в связанном списке (где вы хотите добавить новый узел)
касательно:
struct node p1;
p1.data = d;
p1.next = NULL;
*q=&p1;
это создает новый «узел» в стеке. Однако все в стеке «исчезает», когда функция возвращается.
q
— это указатель на первый «узел» в связанном списке, а не на последний «узел» в связанном списке. Предлагайте использовать temp
как (после исправления 1)
указывает на последний «узел» в связанном списке
каждый «узел» должен быть создан в памяти «кучи» через malloc()
или calloc()
, чтобы он все еще существовал после выхода из функции.
касательно:
temp = *q;
*q = malloc(sizeof(struct node))
temp->data = d;
temp->next = NULL;
the error is gone.
НЕТ, ошибка НЕ исчезла. Скорее, это всегда вставляет новый «узел» как второй «узел» в связанном списке. (и разрывает ссылку на следующие узлы связанного списка.)
размещенный код не может вернуть всю выделенную память в кучу (через вызовы free()
). Результатом является утечка памяти для каждого вызова malloc()
.
Вы изменили свой вопрос соответственно после того, как получили ответ. Это не ценится и считается вопросом «движущейся мишени». Пожалуйста, избегайте этого. К счастью, я думаю, что на новый вопрос все еще отвечает мой пост. В противном случае дайте мне знать. Однако я мог бы попросить вас вернуться к вопросу, на который я ответил, а затем указать, чего не хватает в моем ответе... (Я вижу, вы приняли мой ответ сейчас. Я полагаю, что вы все еще воспринимаете его как ответ... .) Веселиться.