C связанный список содержит только первый элемент ... не уверен, что происходит с остальными - PullRequest
1 голос
/ 23 января 2010

Я отправил вопрос несколько дней назад о связанном списке в C. Я думал, что все в порядке, тогда профессор пишет нам по электронной почте, что вместо этой подписи:

int insert_intlist( INTLIST* lst, int n); /* Inserts an int (n) into an intlist from the beginning*/

Он случайно имел в виду:

int insert_intlist( INTLIST** lst, int n); /* Inserts an int (n) into an intlist from the beginning*/

Теперь я подумал, что у меня есть указатель на указатель, и я могу переместить указатель за пределы main, а когда я вернусь к main, у меня все еще будет полный список связанных ссылок.

Он начинает с того, что дает нам:

INTLIST* init_intlist( int n ) 
 {
    INTLIST *lst; //pointer to store node
    lst = (INTLIST *)malloc(sizeof(INTLIST)); //create enough memory for the node
    lst->datum = n; //set the value
    lst->next = NULL; //set the pointer
    return lst; //return the new list
}

Что просто инициализировать список, как в main:

   if (lst==NULL)
                  lst = init_intlist(i);
               else
                  insert_intlist(lst, i); 

lst имеет тип INTLIST *, поэтому он определен как INTLIST * lst. Поэтому я читаю некоторые цифры из текстового файла, например, 1 3 4 9. Предполагается создать связанный список из этого ... поэтому первое число будет идти к init_intlist (1); И это было определено выше. Затем он получает следующий номер 3 в этом случае и вызывает insert_intlist (lst, 3). Ну вот мой insert_intlist, и все, что я хочу сделать, это вставить в начало списка:

int insert_intlist(INTLIST** lst, int n )
 {
    INTLIST* lstTemp; //pointer to store temporary node to be added to linked list
    lstTemp = (INTLIST *)malloc(sizeof(INTLIST)); //create enough memory for the node
    lstTemp->datum = n; //assign the value

    //check if there is anything in the list,
    //there should be, but just in case
    if(*lst == NULL)
       {
          *lst=lstTemp;
          lstTemp->next=NULL;
       }
    else
       { 
          lstTemp->next = *lst; //attach new node to the front
          *lst = lstTemp; //incoming new node becomes the head of the list
       } 

    return 0; 
 }

Так что, если бы список содержал 1, изначально эта функция просто создала бы новый узел, а затем сделала бы этот временный узел-> следующей точкой к началу списка (который я считал первым), а затем переназначила заголовок списка на этот новый временный узел.

Все выглядит так, как будто работает правильно, но когда я пытаюсь вывести свой список на экран, он печатает только номер 1.

Кто-нибудь знает, что я делаю не так?

Ответы [ 4 ]

1 голос
/ 23 января 2010

Вам передают указатель на указатель. Вы хотите изменить указатель, на который указывает указатель, а не указатель на сам указатель. Имеет ли это смысл?

if(lst == NULL)

Здесь вы проверяете, передан ли вам пустой указатель. Хорошая практика для проверки ошибок, но не для того, что вы делали прямо там. Если lst НЕДЕЙСТВИТЕЛЕН, то у вас даже нет указателя на указатель, вы ничего не можете сделать и должны возвращать ненулевой код ошибки, ничего не делая.

Если вы уверены, что ваш указатель не равен NULL, , затем вы смотрите на указатель, на который он указывает (*lst). Указатель на указатель является указателем на первый элемент списка. Если указатель равен NULL, , тогда вы меняете на указатель нового элемента. В основном, когда вы используете lst, вы должны использовать *lst или (*lst). (ПОМНИТЕ: оператор * запускается после оператора ->! Таким образом, чтобы получить поле в объекте, на который указывает указатель, на который указывает lst [pant, pant], вы используйте (*lst)->whatever.)

P.S. Этот вид работы с указателями критически важен , чтобы научиться быть хорошим программистом, особенно с C.

P.P.S. Другая вещь, которую вы ошиблись, это то, что вместо

insert_intlist(lst, i);

Вы должны называть это как

insert_intlist(&lst, i);

... и, для точек брауни, проверьте код возврата на наличие ошибок.

0 голосов
/ 23 января 2010

Проверьте, есть ли lstTemp-> next == NULL после lstTemp-> next = lst;

0 голосов
/ 23 января 2010

Поскольку вы используете указатель на другой указатель в функции вставки, вы можете изменить, на какую ячейку памяти указывает последняя , на самом деле . Я немного изменил код вставки, и он отлично работает:

int insert_intlist(INTLIST** lst, int n )
{
    INTLIST* lstTemp; //pointer to store temporary node to be added to linked list
    lstTemp = (INTLIST *)malloc(sizeof(INTLIST)); //create enough memory for the node
    lstTemp->datum = n; //assign the value

    //check if there is anything in the list,
    //there should be, but just in case
    if(*lst == NULL)
    {
      lstTemp->next=NULL;
      *lst = lstTemp;
    }
    else
    { 
      lstTemp->next = *lst; //attach new node to the front
      *lst = lstTemp; //incoming new node becomes the head of the list
    } 

return 0; 

}

РЕДАКТИРОВАТЬ: я вижу, вы редактировали свой вопрос. В этом случае, возможно, вы неправильно вызываете функцию вставки в main (). Попробуйте это

int main()
{
    INTLIST *head;
    head = init_intlist(42);
    insert_intlist(&head, 41);
    display(head);
    return 0;
}
0 голосов
/ 23 января 2010

Первая проблема, которая возникает у меня в голове, заключается в том, что в insert_intlist() вы делаете lst = lstTemp;. Это должно быть *lst = lstTemp;. Таким образом вы назначаете указатель списка, который вы указали, а не указатель списка (который ничего не обновляет вне функции).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...