2014-12-03 2 views
-2

У меня возникают трудности с моей функцией C-программы. Идея функций заключается в добавлении элемента (newval) в конец связанного списка. Вот мой код (также найти комментарии с ней):Добавление элемента в конец связанного списка -> ошибка

#include <stdlib.h> 

struct list 
{ 

    int val; 
    struct list *next; 
}; 

void add_to_list(struct list *l, int newval) 

{ 

    if (!l) return; //my fried said that I should add this, but I dont really understand why. 
        //and should it be if(l == NULL) rather than if(!l)? 
    while(l->next !=NULL) // I am pretty sure that this while loop is correct 
     l=l->next; 
    l->next = malloc(sizeof(int)) //hmm... is this correct way to allocate memory 
    l->next->val = newval; //not sure about this 
    l->next->next = NULL; //This should be fine 
} 
+0

'l-> next = malloc (sizeof (int))' Это действительно правильный способ выделения памяти, но вы не выделяете достаточно. Вам нужно выделить достаточно, чтобы содержать весь 'struct list'. Измените эту строку на 'l-> next = malloc (sizeof (* (l-> next)))' –

ответ

0

следует выделить

l->next = malloc(sizeof(struct list)); 

вместо

l->next = malloc(sizeof(int)); 

и инициализировать выделенную память с нуля:

memset(l->next, 0, sizeof(struct list)); 
+0

Я не согласен. Зачем использовать 'memset()' для инициализации структуры? Это не достаточно большой объем памяти, чтобы гарантировать это. –

+0

ОК, я не видел в этом случае строки l-> next-> next = NULL -> memset. Я просто хотел, чтобы все было правильно инициализировано. Насколько я знаю, memset отлично работает для минимально возможного размера блока памяти (1 байт). – chrmue

2
l->next = malloc(sizeof(int)); 

Вам нужно выделить память для вашей структуры не для int

l->next = malloc(sizeof(struct list)); 

if(!l) такой же, как if(l == NULL)

+0

Действительно ли (! L) действительно такое же, как если бы (l == NULL). Я думал, что если (! L) означает, что (l == 0)? –

+0

@NerdBergg NULL - 0. Проверьте это http://stackoverflow.com/questions/1296843/what-is-the-difference-between-null-0-and-0 – Gopi

+0

Хорошо, это понятно, но опять же, почему сделать это, если предложение здесь? Я имею в виду, добавьте эту проверку, чтобы, если список пуст, вернитесь. Но зачем возвращаться, если список пуст, не можем ли мы добавить туда элемент newval? Или это означает, что если список пуст, мы не можем добавить что-либо к его концу ... мы должны сначала добавить к нему первый элемент, и это нужно было бы сделать в другой функции? –

0
void add_to_list(struct list *l, int newval) 

Ваша функция объявлена ​​как void. Это означает, что для функции ваша функция сигнализирует об ошибке. Не проблема для кода примера, , но определенно то, о чем вы должны хотя бы знать.

if (!l) return; //my fried said that I should add this, 
        //and should it be if(l == NULL) rather than if(!l)? 

Конструкция (!l) полностью эквивалентна (l != NULL). Это происходит потому, что NULL определяется как «пустого указатель постоянной», и «пустого указателя постоянной» является «Константой выражения целого с значения 0, или такое выражение приводится к типу void *» , В других словах NULL оценивает на ноль.

while(l->next !=NULL) // I am pretty sure that this while loop is correct 
     l=l->next; 

Да, это while петля правильно. Когда цикл завершается, l будет указывать на последний элемент в списке.

l->next = malloc(sizeof(int)) //hmm... is this correct way to allocate memory 

Ваше распределение почти справа. Вы выделяете достаточное количество хранилища для , удерживая один int, но вам действительно нужно достаточно места для хранения struct list. вместо этого используйте l->next = malloc(sizeof(struct list));.

l->next->val = newval; //not sure about this 

Ошибка здесь. Это точно так же правильно, как и следующая строка.

l->next->next = NULL; //This should be fine 

Да, это нормально ..


Однако, в то время как эта часть кода в основном правильно, запрещая malloc(), что уже была покрыта,

l->next = malloc(sizeof(int)) //hmm... is this correct way to allocate memory 
    l->next->val = newval; //not sure about this 
    l->next->next = NULL; //This should be fine 

метод, используемый здесь немного необычно. Это связано с тем, что при назначении новой памяти вы назначаете указатель непосредственно на l->next и затем инициализируете его.

Что чаще делается это todeclare указателя, такие как struct list *tmp = NULL в начале функции, и при выделении, назначить новую память tmp. Затем, , инициализируйте новый элемент списка, на который указывает tmp, и , затем добавьте новый элемент списка с новым именем в конец списка . Хотя это включает в себя несколько больше кода, разделяет два шага создания нового элемента списка и добавления элемента в конец списка.

void add_to_list(struct list *l, int newval) 
    { 
     struct list *tmp = NULL; 

     if (!l) return; // If no valid list, return. 

     tmp = malloc(sizeof(struct list)); // Allocate new list element 
     tmp->val = newval;     // and fill it up. 
     tmp->next = NULL; // End of the list always points nowhere. 

     while(l->next !=NULL) // find end of list. 
      l=l->next; 

     l->next = tmp; // Attach new list element to end. 

     return; 
    } 

Кроме того, делая это таким образом избежать возможной путаницы, которая может возникнуть от присвоения значений через l->next указатель.

Смежные вопросы