Как удалить узел из связанного списка после печати содержимого? - PullRequest
0 голосов
/ 01 ноября 2011

У меня есть программа на c, которая получает сообщения от разных клиентов и серверов.Когда приходят сообщения, он добавляет сообщение в этот список.После добавления сообщения в список я печатаю его на экране и на других серверах.Но я хочу удалить узел, который содержит сообщение, после того, как оно напечатано, поэтому, когда вызывается функция печати, печатается только новые сообщения.Как я могу удалить узел после печати?

Вот моя структура:

typedef struct trade_list {
    char* trader_msg;
    u_int32_t id_of_sender;
    int sender_timer;
    int local_time;

    struct trade_list *next;
}trade_list;

trade_list *head = NULL;

А вот как я печатаю:

  void print_trades()
    {

        trade_list * newnode = head;
        trade_list *previous = NULL;

            while (newnode) {

             previous = newnode;

              if ((elapsed - newnode->local_time >= 8)) 

             printf ("%s\n", newnode->trader_msg);
             newnode = newnode->next;

                if (previous == NULL)
                    head = newnode->next;
                else
                    {
                    previous->next = newnode->next;

                    free(newnode);
                    }
                }
}

Таким образом, дает мне сегментациюнеисправность.Я попытался изменить newnode-> рядом с просто newnode в остальной части.previous->next = new node; Это не дало мне ошибки, но не стерло узел, так как он продолжал печатать этот узел каждый раз, когда вызывалась функция печати

Ответы [ 3 ]

0 голосов
/ 01 ноября 2011

В начале вашей функции:

trade_list *prev = NULL;

На каждой итерации в вашем цикле перед newnode = newnode->next; добавьте prev = newnode.

Затем удалите:

if (prev == NULL) /* replace the head */
   head = newnode->next;
else
   prev->next = newnode->next;

/* free newnode? */

Довольно просто.

РЕДАКТИРОВАТЬ : у вас действительно должны быть некоторые функции, такие как list_create, list_add, list_remove, связанные с вашей структурой данных, а не просто бросок какудалить код в функцию печати.Это первое, что я делаю, когда создаю какую-либо структуру данных.

Другой вариант - иметь связанный список, например:

typedef struct trade_node {
   char* trader_msg;
   u_int32_t id_of_sender;
   int sender_timer;
   int local_time;

   struct trade_node *next;
} trade_node;

typedef struct trade_list {
   trade_node *head;
   /* trade_node *foot; ? */
   size_t length;
} trade_list;

EDIT2 : что касаетсяизмените print_trades на что-то вроде:

void print_trades()
{
   trade_list *prev = NULL, *next;
   trade_list *newnode = head;

   while (newnode) {

      if ((elapsed - newnode->local_time >= 8)) {    
         printf ("%s\n", newnode->trader_msg);

         /* temp variable for newnode->next */
         next = newnode->next;

         if (prev == NULL) /* replace the head */
            head = next;
         else
            prev->next = next;

         /* free newnode->trader_msg? */
         free(newnode);

         /* don't update prev */
         newnode = next;
      }
      else {
         prev = newnode;
         newnode = newnode->next;
      }

   }
}

В вашем коде previous никогда не будет NULL, так как вы установили его в newnode в начале цикла, и newnode также не должно равняться newnode->next до тех пор, пока newnode не будет полностью обработано.Вы также используете newnode после того, как free d.

0 голосов
/ 01 ноября 2011

Потратьте некоторое время, чтобы рассмотреть обработку связанного списка и удаление элементов из связанных списков ... как только ваша "печать" будет выполнена, просто выполните удаление ...

По сути, вы хотите иметь несколько объектов Trade_list Pointer, которыеуказать на удаляемый узел и предыдущий узел.Сделайте так, чтобы «следующий» узел предыдущего узла указывал на следующий узел, который нужно удалить, и затем освободите память на удаленном узле ...

Start...
NODE1->NODE2->NODE3
  ^      ^
  |      |
*temp1 *temp2

temp1 = NODE1;
temp2 = NODE2;  //or temp2 = temp1->next;

Next...
  +-------------+
  |             V
NODE1  NODE2->NODE3
  ^      ^
  |      |
*temp1 *temp2

temp1->next = temp2->next;
free(temp2);

After...
NODE1-------->NODE3

//temp1 still = NODE1
//temp2 = null

Сделайте так, чтобы объекты-указатели перебирали список с помощью вашего оператора whileцикл, как вы идете, чтобы вы не в конечном итоге не синхронизированы.Также не забудьте проверить на null

0 голосов
/ 01 ноября 2011

Вместо того, чтобы print_trades зависеть от глобальной переменной head, сделайте так, чтобы она принимала эту «голову» в качестве аргумента и печатала оттуда. Намного лучше в дизайне.

 void print_trades(trade_list* head){ ... }

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

Удаление списка обычно выполняется путем вызова free(ptr) на каждом из указателей. Поскольку вы знаете, как добавлять узлы в список, вы будете знать, как правильно инвертировать это.

...