c - 打印链表内容只打印第一个节点

标签 c linked-list traversal

这是代码的更新版本。每次客户端向服务器发送消息(可以是多个客户端)时,我都尝试在链接列表中添加一些信息。每次新消息到达时,该函数都会检查其时间,以便根据其当前时间将其添加到前一个节点之前或之后的列表中。服务器必须按到达顺序打印消息。如果有相同的时间戳,那么它应该使用服务器的 id 来对相同的时间戳进行排序。

这是我的列表结构:

   '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 add_transaction (char* received_msg_IN, int curr_time_IN, u_int32_t my_id_IN, int elapsedIn)
{ 
 /* Find the node with the smallest time >= curr_time_IN.  'found' starts as NULL, then
        is always the node before 'cur'.  'cur' moves through the list until its time is
        less than 'curr_time_IN'.  So at the end, 'cur' is the first node that's too 
        far in, and 'found' is either NULL or the node we insert after. */

    trade_list *newnode, *cur, *found;


     found = NULL;
  for (cur = head; cur && cur->sender_timer <= curr_time_IN; cur = cur->next)
     found = cur;


    if (found) {
      /* If 'found' isn't NULL, we're inserting after it*/
            /* Times match: Sort out in another way*/

      } else {
            newnode = malloc(sizeof(*newnode));
            newnode->trader_msg = malloc(strlen(received_msg_IN)*sizeof(received_msg_IN));
            strcpy(newnode->trader_msg,received_msg_IN);
            newnode->sender_timer = curr_time_IN;
            newnode->id_of_sender = my_id_IN;
            newnode->local_time = elapsedIn;
            newnode->next = found->next;
            found->next = newnode;

            }
    } else {                

        /* No node with more recent time found -- inserting at 'head' */
       newnode = malloc(sizeof(*newnode));
       newnode->trader_msg = malloc(strlen(received_msg_IN)*sizeof(received_msg_IN));
       strcpy(newnode->trader_msg,received_msg_IN);
       newnode->sender_timer = curr_time_IN;
       newnode->id_of_sender = my_id_IN;
       newnode->local_time = elapsedIn;
       newnode->next = head;
       head = newnode;
         }   

出现新问题后进行编辑

后来我设法使用排序方法对列表进行排序。现在我的 list 已经排序得很好了。它打印得很好,现在出现的新问题是我想在打印后删除当前节点。因此,打印后它就会被删除。我使用了以下函数,但我的应用程序崩溃了。

void deletefirst (struct trade_list *head) {
    struct trade_list *tmp = *head;         
    if (tmp == NULL) return;            
    *head = tmp->next;                  
    free (tmp);                        
}

我从打印函数中调用此函数:

void print_trades()
{

    trade_list * newnode = head;

        while (newnode) {

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

          }
}

如何删除当前节点并继续?

最佳答案

只要至少有一个节点,打印列表的方式就应该可以正常工作。我建议将 do { ... } while() 更改为 while() { ... } ,这样它在列表时仍然有效为空且 headNULL:

trade_list *currentnode = head;
while (currentnode) {
  printf ("Trade: %s Time: %d ID: %d\n", 
      currentnode->trader_msg,
      currentnode->sender_timer,
      currentnode->id_of_sender);
  currentnode = currentnode->next;
}

不过,添加到列表的方式存在一些问题。当 head 不为 null 时,您将删除其到列表其余部分的链接:

if (head == NULL) 
    {
   ... /* skipped for brevity */
    }
else
    {
    currentnode->next = NULL;
    head = currentnode;
    }

因为此时currentnode == head,您将head->next指向NULL(如果有另一个节点,您将把它扔掉),然后将 head 分配给自身。

您的插入代码总体上看起来不正确。如果您只想在列表的开头插入,您只需要类似:

trade_list *newnode = malloc(sizeof(trade_list));
/* *** Fill out newnode's fields here *** */
newnode->next = head;
head = newnode;

如果你想在任意节点之后插入,你必须首先通过遍历列表找到它,然后执行类似的操作(将后面的时间保留在列表的头部):

trade_list *newnode, *cur, *found;
/* Find the node with the smallest time >= curr_time_IN.  'found' starts as NULL, then
   is always the node before 'cur'.  'cur' moves through the list until its time is
   less than 'curr_time_IN'.  So at the end, 'cur' is the first node that's too far in,
   and 'found' is either NULL or the node we insert after. */
found = NULL;
for (cur = head; cur && cur->sender_timer >= curr_time_IN; cur = cur->next)
  found = cur;

if (found) {
  /* If 'found' isn't NULL, we're inserting after it (or skipping if the times match,
     since that seems to be what the original code was trying to do) */
  if (found->sender_timer == curr_time_IN) {
    /* Times match: skip it */
    printf("SKIPPED\n");
  } else {
    /* inserting after 'found' */
    newnode = malloc(sizeof(*newnode));
    /* *** Fill out newnode's fields here *** */
    newnode->next = found->next;
    found->next = newnode;
  }
} else {
  /* No node with more recent time found -- inserting at 'head' */
  newnode = malloc(sizeof(*newnode));
  /* *** Fill out newnode's fields here *** */
  newnode->next = head;
  head = newnode;
}

评论后编辑:

要更改列表以按时间降序排序,然后在时间匹配时按 ID 升序排序,只需进行一些更改。

编辑 由于查找节点的原始 for 循环会继续到满足条件的最后节点,因此我们只需在循环中添加一个测试即可在到达时中断正确的...也就是说,如果下一个节点具有相同的时间和更高的 ID,则中断,因为在这种情况下,我们希望在它之前插入。 (之前的编辑有缺陷......对此表示抱歉)。

此外,不再需要之后的 if (found->sender_timer == curr_time_IN) 检查,因为没有跳过,并且按 ID 排序是由新的 for 处理循环。

因此该部分代码变为:

/* original search */
for (cur = head; cur && cur->sender_timer >= curr_time_IN; cur = cur->next) {
  /* *** added condition for ID sort */
  if (cur->sender_timer == curr_time_IN && cur->id_of_sender >= my_id_IN) break;
  found = cur;
}

if (found) {
  /* If 'found' isn't NULL, we're inserting after it */

  /* CHANGED: no need to skip when times are equal */
  newnode = malloc(sizeof(*newnode));
  /* *** Fill out newnode's fields here *** */
  newnode->next = found->next;
  found->next = newnode;

} else {
   /* No node with more recent time found -- inserting at 'head' */
  newnode = malloc(sizeof(*newnode));
  /* *** Fill out newnode's fields here *** */
  newnode->next = head;
  head = newnode;
}

关于c - 打印链表内容只打印第一个节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7919754/

相关文章:

C - realloc() 函数 - 证明它会损坏数据

创建链表+添加新节点+打印列表,但无法弄清楚为什么它不起作用

c++ - 链表追加方法

algorithm - 图论深度优先搜索

c - TCP connect()(在 C 中)总是失败,即使服务器可以通过 telnet 访问

c - gdb watchpoint 不触发内存地址

jQuery 扫描具有特定类别的所有项目的 UL 结构

javascript - 如何编写这样的选择器 : $ ('.classname.active' ) if '.classname' is stored in a $var?

c - 如何在 ubuntu 中计算 C 程序的运行时间

使用链表计算 C 中未知但巨大的文本文件中的单词数