Void函数处理类型的指针

时间:2015-02-22 19:15:14

标签: c data-structures linked-list

我正在使用这个链接列表库,但是在列出已保存的客户端时遇到问题,我只获得了最后一个插入客户端。 注意到list_iterator_next()函数返回一个void指针, 我的代码中有什么问题?

#include <stdio.h>
#include <string.h>

#include "simclist.h"   /* use the SimCList library */


int main() {

    // initialize clients
    list_t clients;

    // structure to append
    typedef struct client{
        char ip[45];
        int port;
    } client;

    client client1;

    int i;
    char ip[45];
    int port;

    // initialize the list
    list_init(&clients);

    for( i  = 1 ; i <= 3; i++ ){
        printf("Insert your ip: ");
        scanf("%s", &ip);
        strcpy( client1.ip , ip );

        printf("Insert your port:");
        scanf("%d", &port);
        client1.port = port;

        list_append(&clients, &client1);
    }

    // size of list
    printf("The list now holds %u elements.\n", list_size(&clients));

    // starting iterator session
    list_iterator_start(&clients);
    // check if there is more values
    while (list_iterator_hasnext(&clients)) {
        // get the next value
        client show_client = *(client *)list_iterator_next(&clients); 
        printf("%s:%d\n", show_client.ip, show_client.port);
    }

    list_iterator_stop(&clients);

    list_destroy(&clients);

    return 0;
}

2 个答案:

答案 0 :(得分:0)

这不是一个完整的答案,但您可以使用此类数组查看@JonathanLeffler注释。然后,您将了解列表库是否正在 结构指针,或整个数据结构内容。

请注意i循环中的更改,在&中的字符串标识符之前省略scanf(),并在结构字段上直接使用scanf()。最后 - 注意字符串长度!

client client1[3];
for( i=0 ; i<3; i++ ){
    printf("Insert your ip: ");
    scanf("%44s", client1[i].ip);

    printf("Insert your port:");
    scanf("%d", &client1[i].port);

    if (list_append(&clients, &client1[i]) != 1) {
        printf ("List append failed\n");
        exit (1);
    }
}

修改

回到这一点,答案显而易见。由于int list_append(list_t *restrict l, const void *data)唯一知道的struct client是指向它的void*指针,因此它不可能知道要复制的数据的大小,因此可能知道它创建的列表中的外部数据,仅包含它给出的指针。所以@JonathanLeffler是正确的:通过为每次插入传递相同的struct指针,列表的所有元素都具有相同的指针,因此只有最新的数据。

答案 1 :(得分:0)

正如Jonathan Leffler已经提出的那样,您需要为每个客户端动态分配内存。 SimCList不会为你做那件事;它不能也不会对你的记忆管理负责。

替换此行:

list_append(&clients, &client1);

由:

list_append(&clients, duplicate_client(&client1));

duplicate_client的天真实现是:

client *duplicate_client(client *c)
{
    return memcpy(malloc(sizeof(client)), c, sizeof(client));
}

但强烈建议使用一些异常处理(以防止malloc返回NULL时出现段错误。)

免责声明:我没有对此进行测试。

偏离主题:请花一些时间来防止内存超支; scanfstrcpy不安全。