我在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;
它没有给我一个错误但它没有删除节点,因为它每次调用打印函数时都会继续打印该节点
答案 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_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
。
答案 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