从 C 中的双向链接列表中删除特定项目

Posted

技术标签:

【中文标题】从 C 中的双向链接列表中删除特定项目【英文标题】:Remove a specific item from the two-way link list in C 【发布时间】:2022-01-04 01:48:49 【问题描述】:

我用 C 语言(服务器和客户端)创建了一个程序,其中服务器为连接到服务器的客户端提供聊天室服务。服务器允许您使用加密算法和协议交换数据。为了存储有关客户的信息,我创建了结构并将它们链接到双向链接列表中。现在我正在处理客户端与服务器断开连接的情况,我需要将其从列表中删除并将新列表正确地重新组合在一起。

这是结构客户:

//客户端结构和新的数据类型CLIENT

typedef struct client 
    char address_buffer[100];
    SOCKET sock_fd;
    salt_channel_t channel;
    socklen_t client_len;
    struct sockaddr_storage client_address;
    struct client *p_next;
    struct client *p_previous;
 CLIENT; 

这是列表:

    typedef struct 
    int count;
    CLIENT *p_head;
    CLIENT *p_tail;
 LIST; 

我添加了创建列表、释放列表、创建客户端、列出整个列表、在列表中查找特定客户端(例如通过套接字、插入新客户端等)的功能......但我仍然有问题编写一个函数,从列表中删除特定用户并填充相当空的位置。

我删除特定用户的函数如下所示:

void realese_client(LIST *p_list,
                    CLIENT *p_client)

   CLIENT *p_new_previous;
   CLIENT *p_new_next;

    //p_list has only one p_client
    if ((p_list->p_head->sock_fd == p_client->sock_fd) && (p_list->p_tail->sock_fd == p_client->sock_fd))
    
        free(p_list->p_head);
        free(p_list->p_tail);    
        p_list->p_head = NULL;
        p_list->p_tail = NULL;
    
     //There are some p_client on the p_list but no p_head or p_tail
    else  if (p_list->p_tail != NULL)
       

        p_new_previous = p_client->p_previous;
        p_new_next = p_client->p_next;

        p_new_previous->p_next = p_new_next;
        p_new_next->p_previous = p_new_previous;
        free(p_client);

     //p_list has p_client as p_tail
    else if (p_list->p_tail->sock_fd == p_client->sock_fd)
    

        p_new_previous = p_list->p_tail->p_previous; 
        p_list->p_tail = p_new_previous;
        p_new_previous->p_previous = p_list->p_tail;

        free(p_client);

    
    else 
       //p_list is empty

        printf("List is empty !!!\n");
        printf("Unable to delete p_client !!!\n");
    


当我调用函数时,应用程序崩溃了。

我的插入客户端功能:

//Function for connecting a new node to the list
void  insert(LIST *p_list, 
            CLIENT *p_client)

      //There are some p_client on the p_list
    if (p_list->p_tail != NULL)
       
        //Connecting the last person as a new person
        p_list->p_tail->p_next = p_client; 
        //Joining a new person to a former last person
        p_client->p_previous = p_list->p_tail; 
        //Save a new p_tail
        p_list->p_tail = p_client; 
    
    else 
       //p_list is empty

        //There is none in front of the p_client
        p_client->p_previous = NULL; 
        //Assigning a p_client to the list (head and tail)
        p_list->p_head = p_client; 
        p_list->p_tail = p_client; 
    
    p_client->p_next = NULL;
    p_list->count++;


【问题讨论】:

我建议学习使用调试器。根据您到目前为止所描述的内容,尚不清楚该列表是否一开始就正确构建。所以从简单开始。创建一个包含一个客户的列表。然后尝试删除该客户端。使用调试器并查看指针,看看它们在每个步骤中是否有意义。然后向上移动到更多列表元素。顺便说一句,我没有看到您在删除客户端后减少 count @cryptoTuke 如果 CLIENT *p_client 用作第二个参数是列表的元素,那么列表怎么可能为空 printf("List is empty !!!\n"); printf("无法删除 p_client !!!\n"); ?!什么作为第二个参数传递给函数? 【参考方案1】:

insert函数好像可以正常工作,但是delete函数逻辑有点模糊 我个人更喜欢使用递归方法来处理链表 我没有完全测试这个 sn-p 但我从很久以前编写的旧代码中获取它并相应地对其进行了更改以匹配您的情况 我希望这会有所帮助

CLIENT * deleteNode(CLIENT * head, SOCKET socket_fd) 
  if(head == NULL) return NULL;
  if(head->socket_fd == socket_fd )
    CLIENT *pre = head; 
    head=head->p_next;
    head->p_previous=NULL;
    free(pre);
    return head;
  
  head->p_next=deleteNode(head->p_next,socket_fd);
  return head;


void realese_client(LIST *p_list,CLIENT *p_client)
   //check the validity of function arguments first for safety purposes
   if(p_list == NULL  || p_client == NULL) return;
   SOCKET socket_fd=p_client->socket_fd;
   ClIENT head=p_list->p_head;
   CLIENT tail=p_list->p_tail;
   //if list of the client is empty exit
   if(tail == NULL) return;


   //test if there is one node
   if(head == tail)
      if(head->socket_fd == socket_fd)
         p_list->p_head=NULL;
         p_list->p_tail=NULL;
         free(head);
      
    return;
   

   if(tail->socket_fd == socket_fd)
       p_list->p_tail=tail->previous;
       p_list->p_tail->p_next=NULL;
       free(tail);
       return;
      
   if(head->socket_fd == socket_fd)
       p_list->p_head=head->p_next;
       p_list->p_head->p_previous=NULL;
       free(head);
       return;
   
  
 deleteNode(p_list->p_head,p_client->socket_fd);



【讨论】:

以上是关于从 C 中的双向链接列表中删除特定项目的主要内容,如果未能解决你的问题,请参考以下文章

如何从c中的双向链表中删除节点

我在特定索引(Java)中为链接列表中的节点编写了一个删除方法,但它没有对列表进行任何更改?

不能只删除链接列表中的最后一个元素! (所有其他具有特定值的元素都会被删除)

“从链接列表中删除循环”中的运行时错误

如何将数组列表中的特定项目移动到第一项

如何使用特定项目删除按钮删除列表视图中的项目?