2011-10-31 74 views
0

我有一個程序在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-> next在else部分中的newnode。 previous->next = new node;它沒有給我一個錯誤,但它並沒有刪除節點,因爲它不停地在每次打印功能被稱爲

回答

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永遠由於您在循環開始時將其設置爲newnode,因此newnode也不應等於newnode->next,直到尾部呃newnode已經完全處理完畢。您在freed之後還使用newnode

+0

是的,我有功能添加和排序。我只是不認爲我需要打印,因爲我認爲我足夠簡單,可以在打印功能內完成。你上面提到的代碼正是我以前使用過的,但是對於prev-> next = newnode-> next part不斷出現分段錯誤@AusCBloke –

+0

@AdamAdamou你有沒有檢查'prev == NULL'的情況,頭正在被刪除?如果你沒有,你會從'prev-> next'得到段錯誤,因爲'prev'是'NULL'。 – AusCBloke

+0

是的,我做了檢查。讓我編輯上面的代碼,以便我可以看到我所做的。 –

0

而不必print_trades依賴於全局變量head打印時間節點,使其獲得這個「頭'作爲論據並從那裏打印出來。這是更好的設計明智。

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

然後,如果您將新節點添加到列表的末尾,則可以從第一個新節點開始打印。如果您不使用這些信息而不是打印它們,則不需要將它們存儲在全局列表中。只需在接收它們的函數中使用本地列表,然後打印該列表。

刪除列表通常通過在每個指針上調用free(ptr)來完成。既然您知道如何將節點添加到列表中,您將知道如何恰當地逆轉這一點。

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