【问题标题】:Remove value from a List从列表中删除值
【发布时间】:2017-10-12 03:27:24
【问题描述】:

我正在编写一个程序来创建列表、打印它并从列表中删除(3 个函数)。

Print 和 pushBack 都很好,它们工作得很好,但我不知道如何在 removeFromList() 函数中从列表中取出一个数字。

不要注意名称(如客户端、套接字),这是为了让我的客户端-服务器应用程序保存活动套接字(这就是为什么我需要在客户端断开连接时将它们从列表中删除)。

这里我有 2 个结构:listElement 和 clientList(其中包含指向 listElement 的头元素的指针)

struct listElement
{
    SOCKET socket;
    struct listElement* next;
};

struct clientList
{
    listElement * head;
};

我的 pushBack 函数:

int pushBackСlient(struct clientList* list, int socket)
{
    struct listElement* newClient = (struct listElement*)malloc(sizeof(struct listElement));
    struct listElement* currentElement = list->head;
    newClient->socket = socket;
    newClient->next = 0;
    do
    {
        // IT'S PUSHBACK
        if (list->head == 0)
        {
            list->head = newClient;
            break;
        }
        while (currentElement->next != 0)
        {
            currentElement = currentElement->next;
        }
        currentElement->next = newClient;
    } while (false);

    return 0;
}

我的打印:

void print(struct clientList* list)
{
    struct listElement* currentElement = list->head;
    while (currentElement != 0)
    {
        printf("%d\n", currentElement->socket);
        currentElement = currentElement->next;
    }
}

还有我遇到问题的功能(我制作了调试消息以查看是否正确添加了“套接字”)。我想我不需要前 3 行,但不确定。

更新13/05/2017

void removeFromList(struct clientList* list, int socket)
{
    struct listElement* currentElement = list->head;
    do
    {
        if (list->head == 0)
        {
            return;
        }

        while (currentElement != 0 && currentElement->next != 0)
        {
            if (currentElement->socket == socket)
            {
                printf("currentElement == %d\n", currentElement);
                currentElement = currentElement->next;
                printf("currentElement == %d\n", currentElement);
                free(currentElement);
                //break; // if I only want to remove the first socket?
            }
            currentElement = currentElement->next;
        }
    } while (false);
}

谢谢。

【问题讨论】:

  • 您的第一个也是最重要的错误是认为这是 C!
  • 这是课堂(学习)练习吗?如果不只是使用std::list
  • @Olaf 我不明白你为什么这么说。我也在使用 stdio.h、stdlib.h 和 winsock2.h 库
  • @RichardCritten 这是一个测试任务,但我在干净的 C 语言项目中需要它。
  • @George Z。在 C 和 C++ 之间做出选择。如果它是 C++ 程序,则使用运算符 new 而不是 malloc。如果是 C 程序,则使用 free 而不是 delete。

标签: c list pointers singly-linked-list


【解决方案1】:

对于您的删除功能,我建议如下:

void removeFromList(struct clientList* list, int socket)
{
    struct listElement* aux, prev;
    if(list->head == 0)
        return;

    aux = list->head;
    prev = aux;

    while(aux != 0){
        if(aux->socket == socket) {
            prev->next = aux->next;
            free(aux);
            break; // if you only want to remove the first socket
        }
        prev = aux;
        aux = aux->next;    
    }
} 

至于您的列表结构,我建议使用结构的结构,如下所示:

struct list
{
    int numberOfElements;
    NODE * first;
} LIST;

struct node
{
    ELEMENT * info;
    NODE * prev; // If you want to have a double connection between the nodes
    NODE * next;
} NODE;

struct element
{
    int id;
    /* Other Properties */
} ELEMENT;

它应该让您更好地控制您的列表。

【讨论】:

  • 感谢您的建议和您的功能。我对使用我的结构有点(甚至不是一点)困惑,所以我现在想把它留在它的状态:) 我很感谢你的帮助。至于 remove() 功能 - 我已经编辑了我的问题。我在调试时遇到问题。似乎我无法获得要从列表中删除的正确套接字。并且实际上并没有得到如何处理列表中的第一个元素。谢谢
  • @GeorgeZ。我很高兴能有用。你的问题解决了吗?
  • 并非如此。我做错了,套接字仍然无法移除。我在调试模式下检查:它将套接字值获取到 currentElement 但随后它被更改为列表中的下一个值并且没有删除。
  • 您对如何修复我的新功能有任何想法吗?调试是说“内存读取错误”。我想它会在 free() 之后尝试读取内存但什么也没找到
  • 首先,您将永远不会阅读列表的最后一个元素,因为您的“如果”声明您应该只分析不为 0 且下一个元素不为 0 的元素.其次,你为什么用while(false)。这是没用的。它将只运行一次正文代码。
【解决方案2】:

函数removeFromList 至少是错误的,因为当列表仅包含一个元素时,while 语句的这个条件可能等于 false。在这种情况下,即使这一个元素包含目标 vakue,它也不会被删除。

while (currentElement != 0 && currentElement->next != 0)

函数看起来就像演示程序中显示的那样。

#include <stdio.h>
#include <stdlib.h>

typedef int SOCKET;

struct listElement
{
    SOCKET socket;
    struct listElement *next;
};

struct clientList
{
    struct listElement *head;
};

int pushBackClient( struct clientList *list, SOCKET socket )
{
    struct listElement *newClient = malloc( sizeof( struct listElement ) );
    int success = newClient!= NULL;

    if ( success )
    {
        newClient->socket = socket;
        newClient->next   = NULL;

        struct listElement **current = &list->head;

        while ( *current != NULL ) current = &( *current )->next;

        *current = newClient;
    }

    return success;
}


int removeFromList( struct clientList *list, SOCKET socket )
{
    int success;

    struct listElement **current = &list->head;

    while ( *current != NULL && ( *current )->socket != socket ) 
    {
        current = &( *current )->next;
    }

    if ( ( success = *current != NULL ) )
    {
        struct listElement *tmp = *current;
        *current = ( *current )->next;

        free( tmp );
    }

    return success;
}

void print(struct clientList *list)
{
    for ( struct listElement *current = list->head;
          current != NULL;
          current = current->next )
    {         
        printf( "%d ", current->socket );
    }
}

int main(void) 
{
    const int N = 10;
    struct clientList list = { NULL };

    for ( int i = 0; i < N; i++ ) pushBackClient( &list, i );

    print( &list );
    putchar( '\n' );

    for ( int i = 0; i < N; i++ )
    {
        if ( i % 2 == 0 ) removeFromList( &list, i );
    }

    print( &list );
    putchar( '\n' );

    for ( int i = 0; i < N; i++ )
    {
        if ( i % 2 == 1 ) removeFromList( &list, i );
    }

    print( &list );
    putchar( '\n' );

    return 0;
}

程序输出是

0 1 2 3 4 5 6 7 8 9 
1 3 5 7 9 

你至少需要添加一个函数来释放列表中的所有元素。

【讨论】:

  • 非常感谢,它非常有效。昨天我写了几乎相同的功能,它也可以工作。感谢您关注我的问题:)
猜你喜欢
  • 2021-11-09
  • 1970-01-01
  • 2022-09-29
  • 2013-04-12
  • 2016-02-17
  • 2012-05-19
  • 2022-01-22
  • 1970-01-01
  • 2015-01-23
相关资源
最近更新 更多