打印内容后如何从链表中删除节点?

时间:2011-10-31 22:10:57

标签: c linked-list nodes

我在c中有一个程序,它接收来自不同客户端和服务器的消息。当消息进入时,它会将消息添加到该列表中。将消息添加到列表后,我将其打印在屏幕上和其他服务器上。但我想在打印后删除包含该消息的节点,因此当调用print函数时,只打印新消息。如何在打印后删除节点?

这是我的结构:

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

因此给我一个分段错误。我尝试在else部分中更改newnode->旁边的newnode。 previous->next = new node;它没有给我一个错误但它没有删除节点,因为它每次调用打印函数时都会继续打印该节点

3 个答案:

答案 0 :(得分:0)

不要让print_trades依赖全局变量head,而是让它接收这个'head'作为参数并从那里打印。设计明智得多。

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

然后,如果要将新节点添加到列表末尾,则可以从第一个新节点开始打印。如果您不使用此信息而不是打印它们,则无需将它们存储在全局列表中。只需在接收它们的函数中使用本地列表,然后打印该列表。

通常通过在每个指针上调用free(ptr)来删除列表。由于您知道如何将节点添加到列表中,因此您将知道如何适当地反转节点。

答案 1 :(得分:0)

在您的职能开始时:

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_createlist_addlist_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

答案 2 :(得分:0)

花一些时间查看链接列表处理和链接列表中的项目删除...一旦你的“打印”执行只是删除...

基本上你想要一些指向要删除的节点和前一个节点的trade_list指针对象。让前一个节点的“下一个”指向要删除的节点,然后释放已删除节点上的内存......

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